2012-01-19 134 views
2

我有一組數據來自表(TableA),它通過TableB與自身相關。 TableA的家長在TableA有孩子。這些孩子也可能有孩子。這裏什麼都不好。Streaming SQL Server 2008遞歸CTE

我有一個從TableA我需要操作的頂層集合的行。在我可以操作這些行之前,我必須讓每個孩子都行。我必須能夠在我的應用程序中儘可能快地在TableA(以及它的子項)的每個頂級行上操作。

我找不到辦法做到這一點。

使用遞歸CTE(TableA頂級設置爲錨點,TableB->TableA連接爲聯合)不符合要求。來自TableA的整個頂層集合在CTE中返回,然後在子級的第2層上工作。然後它在3級上工作,然後是4級等等。由於我的頂級集合有400,000多行,因此我的客戶端應用程序無法開始處理行,直到ENTIRE數據集在服務器上成批完成。

我需要一個更好的方式來做到這一點。我嘗試將一組頂級的TableA行數據流傳輸到客戶端,並讓客戶端爲每個頂級TableA行重複發出遞歸CTE語句。這實際上起作用。但是噪音太大了。由於重複發表聲明,持續的行檢索率太大。

我需要一個創造性的解決方案。

我正在使用的每條記錄CTE的片段。在這個例子中,TableA是Member,TableB是MemberReplacement。我剔除了大部分中間的select語句以及大部分連接。

WITH T_MemberRecurse 
(
    MemberId, 
    IncludedMemberId, 
    Level 
) AS (
    SELECT  Member.Id, 
       Member.Id, 
       0 
    FROM  MemberInput 
    INNER JOIN MemberInputItem 
     ON  MemberInputItem.MemberInputId = MemberInput.Id 
    INNER JOIN Member 
     ON  Member.Id = MemberInputItem.MemberId 
    UNION ALL 
    SELECT  T_MemberRecurse.MemberId, 
       Member2.Id, 
       Level + 1 
    FROM  T_MemberRecurse 
    INNER JOIN Member 
     ON  Member.Id = T_MemberRecurse.IncludedMemberId 
    INNER JOIN MemberReplacement 
     ON  MemberReplacement.MemberId = Member.Id 
    INNER JOIN Member Member2 
     ON  Member2.Id = MemberReplacement.OriginalMemberId 
) 
SELECT  Member.Id, 
      T_MemberRecurse.IncludedMemberId, 
      T_MemberRecurse.Level, 

FROM  MemberInput 
INNER JOIN LotsOfTables 
+0

你能張貼一些樣本代碼和樣本數據嗎? – JNK

+0

剛做過。我添加了每個記錄的CTE示例。發佈示例的一個問題是,我的例子甚至都沒有被設計出來解決問題的權利。 – wasabi

+0

對不起,*'沒有設計正確'* - 你是什麼意思?你目前的解決方案是否會返回不正確的結果,或者它們效率不夠? –

回答

1

我現在想着這一點,但第一次在黑暗中刺,可以幫助,由於經驗,我已經受夠了鏈接的服務器,其中迫使行到行操作的性能改進2個數量級。

使用一個參數(即所需的成員標識)將CTE轉換爲行集返回函數。

然後:

SELECT 
    * 
FROM 
    Member M 
    CROSS APPLY dbo.MemberChildren(M.Id) C 
WHERE 
    {Conditions for desired set of Members here} 
WITH (FAST 20); 

請讓我知道,如果這個工程。這個想法是迫使發動機先進行深度優先而不是先進行。這可能會降低整體服務器的性能,但理論上應該讓您的客戶端開始處理一些數據行。

更新

設想二:分別得到了家長和孩子的信息,並執行,從邏輯上講,合併在客戶端加入。 (一個有序的嵌套循環,只有在它不匹配時纔會使有序的第二個/內部輸入前進。)使用鍵範圍或row_number立即獲取較小的塊。或者獲取整個父集,然後獲取較小的一組子行。

更新2

思路3:取而代之的是遞歸CTE的,使用5號普通的香草加入以獲得您需要的所有數據。這聽起來很糟糕,但應該讓你做FAST 100開始數據。

+0

嗯。這可能會起作用。試圖避免聲明一個函數來完成它,但這可能是適當的,並可能正常工作。星期一我會放棄它。 – wasabi

+0

與包含外部參考的子查詢的交叉應用理論上可以先深入,但也許不是。這樣的功能。 – ErikE

+0

如果你可以把CTE放在子查詢中,我會在一段時間之前解決它。 =/ – wasabi