2010-05-24 107 views
1

我們正在爲我們的網站安裝新的論壇(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 [email protected]) and 
    ((@ParentID is null and b.ParentID is null) or [email protected]) 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

看看Do you use [email protected] 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) 

也許你的函數是搞亂這個事情了,硬編碼的東西,而不是函數調用,看看它是否有劇烈的差異

+0

是的,就是這樣。拋出一個隨機的topicID使它在271ms內執行。你是如何縮小它的? – cschear 2010-05-24 18:46:58

+1

因爲我知道函數是如何工作的......他們通常不應該在WHERE子句或聯接中使用 – SQLMenace 2010-05-24 18:52:42

+0

而且因爲SQLMenace當然很棒。 – HLGEM 2010-05-24 19:39:01

2

有了這些類型的IO統計,查詢必須b鎖定。在SP運行時,請檢查sys.dm_exec_requests,查看您的過程運行窗口(@@ SPID)的session_id,並參閱blocking_session_id,wait_type,wait_time和wait_resource。這些應該引導你瞭解阻塞的原因。

+0

雖然這並沒有幫助這個查詢,肯定會使用。謝謝。 – cschear 2010-05-24 18:49:34

0

我注意到這個表是你最大IO的罪魁禍首:

表'yaf_UserGroup'。掃描計數231,邏輯讀取693,物理讀取0,預讀0,lob邏輯讀取0,lob物理讀取0次,lob預讀0

我還注意到,違規表是在查詢中的任何地方都沒有提及。這意味着它必須在查詢中使用的某個UDF中引用。我的猜測是,UDF阻止查詢有效地使用您的yaf_UserGroup表上的索引。您可以通過將有問題的UDF的邏輯直接合併到查詢中來糾正此問題。

最後,無論你如何解決這個問題,它看起來像yaf是開源的。這意味着您應該將您的修補回饋給原始項目。這將有助於保持代碼與基礎項目的內聯更緊密,以便將來的更新不會撤銷您的性能修復。

1

我沒有看到你的執行計劃有什麼不好。

大多數情況下,另一個會話會鎖定您的查詢,或者您的服務器負荷過重。

1

相關聯的子查詢是逐行運行的。將它們轉換爲連接。

與您的UDFs一樣的東西。將它們轉換爲連接可以加快速度,因爲它們也是逐行運行的。

什麼SQL威脅說。