Нужна помощь с рекурсивной производительностью CTE. Ниже CTE работает очень медленно, так как пытается рекурсивно извлекать иерархические данные. Таблица большая с каждым корневым идентификатором, имеющим до 3 рекурсивных элементов. Может быть около 200000 или более корневых идентификаторов. Я знаю, что рекурсивные CTE медленны для огромного набора данных, так как для каждого корневого элемента в якоре он будет рекурсивным.
Схема:
Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)
Над таблицей есть более 1 миллиона строк.
Запрос 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
)
Мы не можем изменить схему таблицы и использовать heirarchyid. Я тоже пробовал цикл 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 должен быть помещен в буфер, но в виде материализованной и проиндексированной вручную таблицы он может работать лучше на последующих этапах.
Даже при большой активности, мне кажется, что кто-то должен быть заблокирован, если операции DML изменяют данные, которые читает этот процесс.
Поэтому я настоятельно рекомендую сделать снимок иерархии.
Кроме того, у вас есть ряд других ВНУТРЕННИХ СОЕДИНЕНИЙ - вам следует проверить, действительно ли это вообще CTE и существуют ли какие-либо индексы, которые отсутствуют, чтобы сделать эти объединения эффективными. План выполнения должен сказать вам это.
Похоже, в предложении WHERE есть несколько вещей, которые могут помочь сократить некоторые операции (и определить, какие индексы могут быть лучшими)), но трудно сказать, не глядя на план выполнения или индексы.
источник