递归 CTE 性能

njv*_*vds 8 performance sql-server cte sql-server-2008-r2 recursive

需要有关递归 CTE 性能的帮助。低于 CTE 的运行速度非常慢,因为它试图以递归方式提取分层数据。表很大,每个根 ID 最多有 3 个递归 itemid。可能有大约 200000 个或更多的 root id。我知道递归 CTE 对于庞大的数据集来说很慢,因为对于锚点中的每个 rootid,它都会递归地进行 itemid。

架构:

Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)
Run Code Online (Sandbox Code Playgroud)

上表有超过 100 万行。

CTE 查询:

; With rootcte as

( select itemid from RootItem where rootid is null

union all

  select r.itemid as RootId , i.itemid from RootItem i join rootcte r
    on i.rootid = r.itemid
)
Run Code Online (Sandbox Code Playgroud)

我们无法修改表架构并使用层次结构。我也试过 while 循环,但这也很慢。

有没有其他方法可以优化此查询?

 ; With rootcte as

( select itemid from RootItem where rootid is null

 union all

 select r.itemid as RootId , i.itemid from RootItem i join rootcte r
 on i.rootid = r.itemid
) 
  SELECT  
     Cust.CustomerID  
    , Cust.BusinessName  
    , sCust.RegionCustomerID  
    , ord.OrderID  
    , ord.OrderItemID  
    , prd.ProductCode  
    , rc.itemid
    , rc.rootid 
    , mf.FileID  
FROM  
    vw_Customer Cust  
    INNER JOIN SrcCustomer scust ON Cust.CustomerID = sCust.RegionCustomerID  
    INNER JOIN OrderItem ord ON Cust.MasterCustomerID = ord.MasterCustomerID  
    INNER JOIN Product ON ord.ProductID = Product.ProductID  
    INNER JOIN rootcte rc ON ord.RootOrderId = rc.Rootid   
    INNER JOIN MFolder mf ON mf.mfolderid = rc.itemid  
    INNER JOIN MVersion mv ON mv.mfolderversionid = mf.mfolderid   
    WHERE ord.IsActive = 1  and product.IsSelling = 1 and mf.fileid in (23,45,29)
     and mv.isdeleted = 'N' 
Run Code Online (Sandbox Code Playgroud)

我还与 BI 组合作更改查询逻辑并过滤 cte 本身的数据,将几个联接和条件移动到 cte.. 感谢所有评论。

Cad*_*oux 3

你说层次结构被修改了。据推测,当该操作运行时,会发生一定程度的阻塞?

即使层次结构发生了变化,项目的根源是否也发生了变化?

您是否考虑过将映射表从根映射到项目并为其建立索引所需的时间?

我想查看执行计划以了解发生了什么 - CTE 应该被假脱机,但作为手动物化和索引表,它可能在后续步骤中表现更好。

即使活动繁重,在我看来,如果 DML 操作正在更改该进程正在读取的数据,则必须阻止某人。

所以我强烈考虑拍摄层次结构的快照。

此外,您还有许多其他 INNER JOIN - 您应该检查它是否实际上是 CTE,以及是否缺少任何索引来使这些连接有效。执行计划应该告诉你这一点。

WHERE 子句中似乎有很多内容,这些内容可能有助于减少一些操作(并确定哪些索引可能是最好的)),但如果不查看执行计划或索引,就很难判断。