2012-01-19 136 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