SQL Query获得了很多超时

时间:2011-07-18 16:26:05

标签: sql sql-server stored-procedures timeout

我有一个大型数据库表(SQL Server 2008),我存储了所有论坛消息(该表目前有超过450万个条目)。

这是表架构:

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 

我得到的错误如下:“超时已过期。操作完成前经过的超时时间或服务器没有响应”

我正在查看执行计划,唯一看起来可疑的是查看该查询在forummessage表中的密钥查找中的成本约为75%-87%(它有所不同)不明白为什么,因为我把它设置为群集,所以我希望它会更有效率)。我总是在这种假设下,当你搜索聚簇索引时,查询应该非常有效。

有没有人知道如何改进此问题以及此查询以获取消息及其回复?

感谢。

4 个答案:

答案 0 :(得分:0)

我想到了两个建议:

  • 删除丑陋 OR并为条件添加UNION(代码如下)
  • 您必须在ReplyToMessage
  • 上拥有非聚集索引

作为最后的手段,创建一个非聚集索引并将MessageIdReplyToMessage放在那里。 (请参阅我在这里的另一个问题的答案Why does this Sql Statement (with 2 table joins) takes 5 mins to complete?


CODE:

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 

答案 1 :(得分:0)

为什么你在做ORDER BY MessageId,是否需要订购?

尝试重构您的SELECTSELECT FROM Forum,然后加入Member,最后加入LEFT JOIN ForumMessage。因此,从小到大订购表

答案 2 :(得分:0)

根据您运行的MS SQL Server的版本,您还可以尝试使用分区表重新创建表,以提高SELECT性能。

答案 3 :(得分:0)

ReplyToMessage上创建索引:

CREATE INDEX
        IX_ForumMessage_ReplyToMessage
ON      ForumMessage (ReplyToMessage)

这很可能导致两个索引搜索(PRIMARY KEY上的MessageIdReplyToMessage上的索引)与合并或散列连接相关联,而不是一个完整的表扫描您现在拥有的。

相关问题