Рекурсивная производительность CTE

8

Нужна помощь с рекурсивной производительностью 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 .. Спасибо за все комментарии.

njvds
источник
2
зачем вам все иерархии? Не должно быть места где-то, поэтому вы рассчитываете только те записи, которые намереваетесь использовать. Конечно, вам не нужно создавать миллионы иерархий каждый раз, когда вы запускаете это.
HLGEM
Это дополнительный отчет, который запускается около 5-6 раз в рабочее время и требует выполнения для всего набора данных. Я мог бы предварительно загрузить данные, если данные были статическими или вставлялись не часто, но в этом случае частые операции DML выполняются с этой таблицей в БД.
njvds
Какие индексы у вас есть в этой таблице?
ypercubeᵀᴹ
ItemID является первичным ключом, а также нет кластеризованного индекса для itemid и rootid.
njvds
1
Вы должны показать запрос, который вы на самом деле используете. Как и сейчас, все, что вы делаете, это сложный способ вернуть все ItemID из таблицы. Рекурсивный CTE не добавляет никакой ценности.
Микаэль Эрикссон

Ответы:

3

Вы говорите, что иерархия изменяется. Предположительно, когда эта операция выполняется, существует ли какое-то количество блокировок, которое происходит тогда?

Даже если меняется иерархия, меняются ли корни предметов?

Вы смотрели, сколько времени потребуется, чтобы просто сделать таблицу сопоставления от корня к элементу и проиндексировать ее?

Я хотел бы увидеть план выполнения, чтобы увидеть, что происходит - CTE должен быть помещен в буфер, но в виде материализованной и проиндексированной вручную таблицы он может работать лучше на последующих этапах.

Даже при большой активности, мне кажется, что кто-то должен быть заблокирован, если операции DML изменяют данные, которые читает этот процесс.

Поэтому я настоятельно рекомендую сделать снимок иерархии.

Кроме того, у вас есть ряд других ВНУТРЕННИХ СОЕДИНЕНИЙ - вам следует проверить, действительно ли это вообще CTE и существуют ли какие-либо индексы, которые отсутствуют, чтобы сделать эти объединения эффективными. План выполнения должен сказать вам это.

Похоже, в предложении WHERE есть несколько вещей, которые могут помочь сократить некоторые операции (и определить, какие индексы могут быть лучшими)), но трудно сказать, не глядя на план выполнения или индексы.

Кейд Ру
источник
Почему операция DML блокирует SELECT? SQL Server все еще так ограничен?
a_horse_with_no_name
@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx возможно, но пользователь упомянул о высокой активности, поэтому ему нужно будет рассмотреть свою стратегию
Cade Roux