SQL Query получает много тайм-аутов - PullRequest
2 голосов
/ 18 июля 2011

У меня есть большая таблица базы данных (SQL Server 2008), в которой хранятся все мои сообщения на форуме (в настоящее время в таблице содержится более 4,5 миллионов записей).

это схема таблицы:

CREATE TABLE [dbo].[ForumMessage](
    [MessageId] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
    [ForumId] [int] NOT NULL,
    [MemberId] [int] NOT NULL,
    [Type] [tinyint] NOT NULL,
    [Status] [tinyint] NOT NULL,
    [Subject] [nvarchar](500) NOT NULL,
    [Body] [text] NOT NULL,
    [Posted] [datetime] NOT NULL,
    [Confirmed] [datetime] NULL,
    [ReplyToMessage] [int] NOT NULL,
    [TotalAnswers] [int] NOT NULL,
    [AvgRateing] [decimal](18, 2) NOT NULL,
    [TotalRated] [int] NOT NULL,
    [ReadCounter] [int] NOT NULL,
 CONSTRAINT [PK_GroupMessage] PRIMARY KEY CLUSTERED 
(
    [MessageId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Одна проблема, которую я вижу, продолжает возвращаться, это то, что когда я запускаю свою хранимую процедуру, которая выбирает сообщение и все его ответы, я получаюиногда ошибки тайм-аута с сервера SQL.

Это моя хранимая процедура:

select fm1.[MessageId]
      ,fm1.[ForumId]
      ,fm1.[MemberId]
      ,fm1.[Type]
      ,fm1.[Status]
      ,fm1.[Subject]
    ,fm1.[Body]
      ,fm1.[Posted]
      ,fm1.[Confirmed]
      ,fm1.[ReplyToMessage]
      ,fm1.[TotalAnswers]
      ,fm1.[AvgRateing]
      ,fm1.[TotalRated]
      ,fm1.[ReadCounter],
     Member.NickName AS MemberNickName, Forum.Name as ForumName
from ForumMessage fm1 LEFT OUTER JOIN
                      Member ON fm1.MemberId = Member.MemberId INNER JOIN
                Forum On fm1.ForumId = Forum.ForumId
where MessageId = @MessageId or ReplyToMessage=@MessageId
order by MessageId 

ошибка, которую я получаю, выглядит следующим образом: «Тайм-аут истек. Время ожидания истекло дозавершение операции или сервер не отвечает "

Я искал план выполнения, и единственное, что выглядит подозрительно, это то, что запрос имеет стоимость около 75% -87% (это варьируется) при поиске ключа в таблице сообщений форума (что я не понимаю почему, потому что я настроил его как кластеризованный, поэтому я надеялся, что он будет намного более эффективным).Я всегда исходил из того, что при поиске по кластерному индексу запрос должен быть очень эффективным.

Есть ли у кого-нибудь идеи, как можно улучшить эту проблему и этот запрос, чтобы получить сообщение и его ответы?

Спасибо.

Ответы [ 4 ]

0 голосов
/ 18 июля 2011

Создать индекс на ReplyToMessage:

CREATE INDEX
        IX_ForumMessage_ReplyToMessage
ON      ForumMessage (ReplyToMessage)

Это, скорее всего, приведет к двум поискам индекса (над PRIMARY KEY на MessageId и по индексу на ReplyToMessage), связанным с конкатенацией слиянием или хэшем, а не полным сканированием таблицы, которое вы сейчас выполняете .

0 голосов
/ 18 июля 2011

Почему вы делаете ORDER BY MessageId, так ли необходим заказ?

Попробуйте перестроить свои SELECT на SELECT FROM Forum, а затем присоединитесь к Member, и, наконец, LEFT JOIN ForumMessage. Так что заказывайте столы от маленьких до больших

0 голосов
/ 18 июля 2011

В зависимости от версии MS SQL Server, которую вы используете, вы также можете попробовать воссоздать таблицу, используя многораздельные таблицы для повышения производительности SELECT.

0 голосов
/ 18 июля 2011

Два предложения приходят мне на ум:

  • Удалите некрасиво OR и добавьте UNION для условия (КОД НИЖЕ)
  • У вас должен быть некластеризованный индекс в ReplyToMessage

В качестве последнего средства создайте некластеризованный индекс и поместите туда MessageId AND ReplyToMessage. (См. Мой ответ на другой вопрос здесь Почему для выполнения этого оператора Sql (с двумя объединениями таблиц) требуется 5 минут? )


КОД:

select fm1.[MessageId]
      ,fm1.[ForumId]
      ,fm1.[MemberId]
      ,fm1.[Type]
      ,fm1.[Status]
      ,fm1.[Subject]
    ,fm1.[Body]
      ,fm1.[Posted]
      ,fm1.[Confirmed]
      ,fm1.[ReplyToMessage]
      ,fm1.[TotalAnswers]
      ,fm1.[AvgRateing]
      ,fm1.[TotalRated]
      ,fm1.[ReadCounter],
     Member.NickName AS MemberNickName, Forum.Name as ForumName
from ForumMessage fm1 LEFT OUTER JOIN
                      Member ON fm1.MemberId = Member.MemberId INNER JOIN
                Forum On fm1.ForumId = Forum.ForumId
where MessageId = @MessageId
UNION
select fm1.[MessageId]
      ,fm1.[ForumId]
      ,fm1.[MemberId]
      ,fm1.[Type]
      ,fm1.[Status]
      ,fm1.[Subject]
    ,fm1.[Body]
      ,fm1.[Posted]
      ,fm1.[Confirmed]
      ,fm1.[ReplyToMessage]
      ,fm1.[TotalAnswers]
      ,fm1.[AvgRateing]
      ,fm1.[TotalRated]
      ,fm1.[ReadCounter],
     Member.NickName AS MemberNickName, Forum.Name as ForumName
from ForumMessage fm1 LEFT OUTER JOIN
                      Member ON fm1.MemberId = Member.MemberId INNER JOIN
                Forum On fm1.ForumId = Forum.ForumId
where MessageId = @MessageId
order by MessageId 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...