递归CTE性能


8

需要递归CTE性能方面的帮助。低于CTE的速度非常慢,因为它试图以回溯方式提取分层数据。表很大,每个根ID最多具有3个递归itemid。可能有大约200000或更多根ID。我知道对于大型数据集,递归CTE的速度很慢,因为锚中的每个rootid都会递归itemid。

架构:

Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)

上表有超过一百万行。

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
)

我们无法修改表架构并使用继承权。我也尝试了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' 

我还与BI小组合作,以更改查询逻辑并过滤连接和标准移动到cte的cte本身的cte数据。。感谢所有评论。


2
为什么需要所有层次结构?应该在某处没有位置,所以您只计算要使用的记录。当然,您每次运行此命令都不需要构建数百万个层次结构。
HLGEM 2012年

此抵押品报告在一个工作时间内运行约5-6次,需要在整个数据集上运行。如果数据是静态的或不经常插入,则可以预加载数据,但是在这种情况下,频繁的DML操作正在数据库中的此表上运行。
njvds 2012年

您在此表上有哪些索引?
ypercubeᵀᴹ

ItemID是主键,并且在itemid和rootid上也有非聚集索引。
njvds 2012年

1
您必须显示您实际使用的查询。现在,您要做的就是从表中返回所有ItemID的复杂方法。递归CTE不会添加任何值。
Mikael Eriksson 2012年

Answers:


3

您说层次结构被修改了。大概在运行此操作时,那么会发生一些阻塞吗?

即使层次结构在变化,项目的根源也在变化吗?

您是否看过仅使映射表从根到项并为其编制索引所花费的时间?

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

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

因此,我强烈考虑对层次结构进行快照。

此外,您还有许多其他的INNER JOIN-您应该检查实际上是否是CTE,以及是否缺少使这些联接生效的索引。执行计划应该告诉您。

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


为什么DML操作会阻止SELECT?SQL Server仍然受到限制吗?
a_horse_with_no_name 2012年

@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx可能,但是用户提到活动活跃,所以他需要考虑自己的策略
Cade Roux 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.