如何让这个T-SQL CTE运行得更快

问题描述 投票:0回答:1

我希望提高我的家长/孩子 CTE 的表现。我想知道是否有一种新的、更好的、更快的方法。 CTE 只是遍历一个现在包含大约 40 万人的父子树。在 SSMS 中,该过程大约需要 5 到 8 秒。

每个人都通过经典的 CHILD ID(我的代码中的 UserID)与 PARENT ID(我的代码中的 SponsorID)相互关联。 UserID 是带有聚集索引的主键,称为 PK_UserID。 SponsorID 有一个名为 IX_SponsorID 的非聚集索引。

粘贴计划: https://www.brentozar.com/pastetheplan/?id=SyaDlDkC3

   -- Engine To Build Parent/Child
    ;
WITH CTE
AS
    (
        -- The Anchor Person 
        SELECT  UserID
           ,SponsorID
               ,0 AS Level
        FROM CCMUsers 
        WHERE UserID = 45
    
        UNION ALL
        
        -- The Recursive People 
        SELECT e.UserID
              ,e.SponsorID
          ,CTE.Level + 1
        FROM CCMUsers AS e
        INNER JOIN CTE ON e.SponsorID = CTE.UserID
)
select * from CTE
sql sql-server parent-child hierarchy
1个回答
0
投票

添加索引

在 SponsorID 上添加索引以帮助加入性能:

CREATE INDEX idx_SponsorID ON CCMUsers (SponsorID)

使用查询提示

允许无限递归深度的选项(MAXRECURSION 0):

WITH CTE (QUERY OPTION (MAXRECURSION 0)) 
AS 
-- other codes 

增量CTE

一次仅递归一级以减少临时表大小:

;WITH Cte1 AS (SELECT * FROM CCMUsers WHERE UserID = 45),
     Cte2 AS (SELECT * FROM Cte1 UNION ALL 
              SELECT c.* FROM Cte1 JOIN CCMUsers c ON c.SponsorID = Cte1.UserID),
     Cte3 AS (SELECT * FROM Cte2 UNION ALL
              SELECT c.* FROM Cte2 JOIN CCMUsers c ON c.SponsorID = Cte2.UserID)
SELECT * FROM Cte3

优化主播会员搜索

使用覆盖索引进行锚点查找以避免键查找:

CREATE INDEX ix_CCMUsers_covering ON CCMUsers (UserID, SponsorID) INCLUDE (Level)

分区 在 SponsorID 上对 CCMUsers 进行分区,以实现更高效的修剪

© www.soinside.com 2019 - 2024. All rights reserved.