Besoin d'aide avec les performances CTE récursives. Ci-dessous, CTE fonctionne très lentement car il tente d'extraire les données héréditaires de manière récurrente. La table est grande avec chaque id racine ayant jusqu'à 3 itemid récursifs. Il pourrait y avoir environ 200 000 identifiants racine ou plus. Je sais que les CTE récursifs sont lents pour un énorme ensemble de données car pour chaque rootid dans l'ancre, il serait itemid récursivement.
Schéma:
Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)
Le tableau ci-dessus contient plus d'un million de lignes.
Requête 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
)
Nous ne pouvons pas modifier le schéma de table et utiliser heirarchyid. J'ai aussi essayé la boucle mais c'est trop lent.
Existe-t-il un autre moyen d'optimiser cette requête?
; 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'
Je travaille également avec BI group pour changer la logique de requête et filtrer les données dans cte lui-même de déplacer quelques jointures et critères vers cte .. Merci pour tous les commentaires.
Réponses:
Vous dites que la hiérarchie est modifiée. Vraisemblablement pendant que cette opération est en cours, il y a une certaine quantité de blocage qui se produit alors?
Même si la hiérarchie change, les racines des éléments changent-elles?
Avez-vous regardé le temps qu'il faudrait pour créer la table de mappage de la racine à l'élément et l'indexer?
Je voudrais voir le plan d'exécution pour voir ce qui se passe - le CTE devrait être mis en file d'attente, mais en tant que table matérialisée et indexée manuellement, il pourrait mieux fonctionner dans les étapes ultérieures.
Même avec une activité intense, il me semble que quelqu'un doit être bloqué si les opérations DML modifient les données que ce processus lit.
J'envisagerais donc fortement de prendre un instantané de la hiérarchie.
De plus, vous avez un certain nombre d'autres jointures INNER - vous devez vérifier s'il s'agit en fait des CTE et s'il manque des index pour rendre ces jointures efficaces. Le plan d'exécution devrait vous le dire.
Vous semblez avoir quelques éléments dans la clause WHERE qui pourraient aider à réduire certaines opérations (et déterminer quels index pourraient être les meilleurs)), mais il est difficile de le dire sans regarder le plan d'exécution ou les index.
la source