2011-04-22 123 views
5

我有一個自連接的表。您可以將結構視爲標準表來表示組織層次結構。例如表格: -爲遞歸查詢優化CTE

MemberId 
MemberName 
RelatedMemberId 

該表格由50000個樣本記錄組成。我寫了CTE遞歸查詢,它工作得很好。但是,在我的機器(4GB內存,2.4 Ghz Core2Duo,7200 RPM硬盤)上處理5萬條記錄所需的時間大約爲3分鐘。

我該如何提高性能,因爲50000並不是那麼龐大。隨着時間的推移,它會不斷增加。這是查詢,這正是我在我的存儲過程中所具有的。查詢的目的是選擇所有屬於特定成員的成員。例如。在公司的所有者每個人都來。對於經理,除了所有者以外,所有記錄都會被返回。我希望你瞭解查詢的目的。

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO

Alter PROCEDURE spGetNonVirtualizedData 
(
    @MemberId int 
) 
AS 
BEGIN 

    With MembersCTE As 
    (
     Select parent.MemberId As MemberId, 0 as Level 
      From Members as parent Where IsNull(MemberId,0) = IsNull(@MemberId,0) 

        Union ALL 
     Select child.MemberId As MemberId , Level + 1 as Level 
      From Members as child 
       Inner Join MembersCTE on MembersCTE.MemberId = child.RelatedMemberId 
    ) 
    Select Members.* 
     From MembersCTE 
     Inner Join Members On MembersCTE.MemberId = Members.MemberId 
     option(maxrecursion 0) 

END 
GO 

正如你可以看到以提高性能,我還送加入在最後一步,而選擇記錄,使所有不必要的記錄做沒有插入到臨時表中。如果我在CTE的基礎步驟和遞歸步驟中加入(而不是在最後一步選擇),則查詢需要20分鐘才能執行!

MemberId是表中的主鍵。

感謝提前:)

回答

8

在你的錨狀況你有Where IsNull(MemberId,0) = IsNull(@MemberId,0)我想這是隻是因爲當你通過NULL作爲參數=不帶回IS NULL價值觀方面的工作。這將導致掃描而不是尋找。

使用WHERE MemberId = @MemberId OR (@MemberId IS NULL AND MemberId IS NULL)代替哪個 sargable。

此外,我假設你不能有一個索引RelatedMemberId。如果你不應該添加一個

CREATE NONCLUSTERED INDEX ix_name ON Members(RelatedMemberId) INCLUDE (MemberId) 

(雖然你可以跳過包括列位如果MemberId是因爲它會自動包含聚集索引鍵)