解决慢查询

时间:2010-05-24 18:25:42

标签: tsql sql-server-2008

我们正在为我们的网站安装一个新论坛(yaf)。其中一个存储过程非常慢 - 实际上它总是在浏览器中超时。如果我在MSSMS中运行它需要将近10分钟才能完成。如果花了这么长时间,有没有办法找出这个查询的哪个部分?

查询:

DECLARE @BoardID int 
DECLARE @UserID int
DECLARE @CategoryID int = null
DECLARE @ParentID int = null

SET @BoardID = 1
SET @UserID = 2

    select 
    a.CategoryID, 
    Category        = a.Name, 
    ForumID         = b.ForumID,
    Forum           = b.Name, 
    Description,
    Topics          = [dbo].[yaf_forum_topics](b.ForumID),
    Posts           = [dbo].[yaf_forum_posts](b.ForumID),
    Subforums       = [dbo].[yaf_forum_subforums](b.ForumID, @UserID),
    LastPosted      = t.LastPosted,
    LastMessageID   = t.LastMessageID,
    LastUserID      = t.LastUserID,
    LastUser        = IsNull(t.LastUserName,(select Name from [dbo].[yaf_User] x where x.UserID=t.LastUserID)),
    LastTopicID     = t.TopicID,
    LastTopicName   = t.Topic,
    b.Flags,
    Viewing         = (select count(1) from [dbo].[yaf_Active] x JOIN [dbo].[yaf_User] usr ON x.UserID = usr.UserID where x.ForumID=b.ForumID AND usr.IsActiveExcluded = 0),
    b.RemoteURL,
    x.ReadAccess
from 
    [dbo].[yaf_Category] a
    join [dbo].[yaf_Forum] b on b.CategoryID=a.CategoryID
    join [dbo].[yaf_vaccess] x on x.ForumID=b.ForumID
    left outer join [dbo].[yaf_Topic] t ON t.TopicID = [dbo].[yaf_forum_lasttopic](b.ForumID,@UserID,b.LastTopicID,b.LastPosted)
where 
    a.BoardID = @BoardID and
    ((b.Flags & 2)=0 or x.ReadAccess<>0) and
    (@CategoryID is null or a.CategoryID=@CategoryID) and
    ((@ParentID is null and b.ParentID is null) or b.ParentID=@ParentID) and
    x.UserID = @UserID
order by
    a.SortOrder,
    b.SortOrder

IO统计:

Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Active'. Scan count 14, logical reads 28, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_User'. Scan count 0, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Topic'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Category'. Scan count 0, logical reads 28, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_Forum'. Scan count 0, logical reads 488, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserGroup'. Scan count 231, logical reads 693, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_ForumAccess'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_AccessMask'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'yaf_UserForum'. Scan count 1, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

客户统计:

Client Execution Time   11:54:01        
Query Profile Statistics            
  Number of INSERT, DELETE and UPDATE statements    0       0.0000
  Rows affected by INSERT, DELETE, or UPDATE statements 0       0.0000
  Number of SELECT statements   8       8.0000
  Rows returned by SELECT statements    19      19.0000
  Number of transactions    0       0.0000
Network Statistics          
  Number of server roundtrips   3       3.0000
  TDS packets sent from client  3       3.0000
  TDS packets received from server  34      34.0000
  Bytes sent from client    3166        3166.0000
  Bytes received from server    128802      128802.0000
Time Statistics         
  Client processing time    156478      156478.0000
  Total execution time  572009      572009.0000
  Wait time on server replies   415531      415531.0000

Execution Plan

5 个答案:

答案 0 :(得分:5)

看看Do you use Column=@Param OR @Param IS NULL in your WHERE clause? Don't, it doesn't perform,了解如何使用sp_executesql重写它,这将更好。

这看起来像是一个函数调用吗?

 left outer join [dbo].[yaf_Topic] t ON t.TopicID = [dbo].[yaf_forum_lasttopic](b.ForumID,@UserID,b.LastTopicID,b.LastPosted)

也许你的功能搞砸了这个东西,硬编码的东西而不是函数调用,看看它是否会产生巨大的差异

答案 1 :(得分:2)

使用这些IO统计信息,查询必须是阻止的。在SP运行时,检查sys.dm_exec_requests,查看过程运行窗口的session_id(@@ SPID),并查看blocking_session_id,wait_type,wait_time和wait_resource。这些应该指导您阻止的原因。

答案 2 :(得分:1)

我认为你的执行计划没有任何不好。

最有可能的是,另一个会话会锁定您的查询,或者您的服务器负载过重。

答案 3 :(得分:1)

相关子查询逐行运行。将它们转换为连接。

与您的UDF相同。将它们转换为连接应该可以加快速度,因为它们也是逐行运行的。

SQL Menace说的是什么。

答案 4 :(得分:0)

我注意到这张桌子是你最大的罪魁祸首:

  

表'yaf_UserGroup'。扫描计数231,逻辑读取693,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

我还注意到,查询中的任何地方都没有直接提到违规表。这意味着必须在查询中使用的其中一个UDF中引用它。我的猜测是UDF阻止查询有效地使用yaf_UserGroup表上的索引。您可以通过将违规UDF中的逻辑直接合并到查询中来纠正此问题。

最后,无论如何解决这个问题,看起来yaf是开源的。这意味着您应该将修复程序返回到原始项目。通过帮助保持代码与基础项目更加一致,这将使您受益,因此未来的更新不会撤消您的性能修复。