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.. 感谢所有评论。
你说层次结构被修改了。据推测,当该操作运行时,会发生一定程度的阻塞?
即使层次结构发生了变化,项目的根源是否也发生了变化?
您是否考虑过将映射表从根映射到项目并为其建立索引所需的时间?
我想查看执行计划以了解发生了什么 - CTE 应该被假脱机,但作为手动物化和索引表,它可能在后续步骤中表现更好。
即使活动繁重,在我看来,如果 DML 操作正在更改该进程正在读取的数据,则必须阻止某人。
所以我强烈考虑拍摄层次结构的快照。
此外,您还有许多其他 INNER JOIN - 您应该检查它是否实际上是 CTE,以及是否缺少任何索引来使这些连接有效。执行计划应该告诉你这一点。
WHERE 子句中似乎有很多内容,这些内容可能有助于减少一些操作(并确定哪些索引可能是最好的)),但如果不查看执行计划或索引,就很难判断。