我有一组表格(TableA
)中的数据,这些数据通过TableB
与自身相关联。 TableA
中的父母有TableA
的孩子。那些孩子也可能有孩子。这里没什么了不起的。
我有一个来自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 :(得分:1)
我现在正在考虑这个问题,但是由于我在链接服务器上遇到的经验导致逐行操作将性能提高了2个数量级,因此首先在黑暗中可能有所帮助。
将您的CTE转换为具有一个参数的行集返回函数,即所需的成员ID。
然后:
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:使用5个普通的vanilla连接来获取所需的所有数据,而不是递归CTE。这听起来很糟糕,但是应该让你快速完成数据。