Benötigen Sie Hilfe bei der rekursiven CTE-Leistung? Unterhalb läuft CTE sehr langsam, da versucht wird, heirarchische Daten rekusiv abzurufen. Die Tabelle ist groß, wobei jede Root-ID bis zu 3 rekursive Element-IDs enthält. Es könnten ungefähr 200000 oder mehr Root-IDs vorhanden sein. Ich weiß, dass rekursive CTEs für große Datenmengen langsam sind, da sie für jede Rootid im Anker rekursiv itemidieren würden.
Schema:
Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)
Die obige Tabelle enthält mehr als 1 Million Zeilen.
CTE-Abfrage:
; 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
)
Wir können das Tabellenschema nicht ändern und heirarchyid verwenden. Ich habe es auch mit while-Schleife versucht, aber das ist auch langsam.
Gibt es eine andere Möglichkeit, diese Abfrage zu optimieren?
; 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'
Ich arbeite auch mit der BI-Gruppe zusammen, um die Abfragelogik zu ändern und Daten in cte selbst zu filtern, um einige Verknüpfungen und Kriterien nach cte zu verschieben. Vielen Dank für alle Kommentare.
Antworten:
Sie sagen, dass die Hierarchie geändert wird. Vermutlich, während dieser Operation ausgeführt wird, findet dann eine gewisse Blockierung statt?
Auch wenn sich die Hierarchie ändert, ändern sich die Wurzeln für Elemente?
Haben Sie sich die Zeit angesehen, die erforderlich wäre, um die Zuordnungstabelle von root zu item zu erstellen und zu indizieren?
Ich würde gerne den Ausführungsplan sehen, um zu sehen, was passiert - der CTE sollte gespoolt werden, aber als manuell materialisierte und indizierte Tabelle könnte er in den späteren Schritten eine bessere Leistung erzielen.
Selbst bei starker Aktivität scheint es mir, dass jemand blockiert werden muss, wenn DML-Vorgänge Daten ändern, die dieser Prozess liest.
Daher würde ich dringend in Betracht ziehen, eine Momentaufnahme der Hierarchie zu machen.
Darüber hinaus haben Sie eine Reihe anderer INNER JOINs - Sie sollten überprüfen, ob es sich überhaupt um die CTEs handelt und ob Indizes fehlen, um diese Joins wirksam zu machen. Der Ausführungsplan sollte Ihnen das sagen.
Die WHERE-Klausel enthält anscheinend einige Dinge, die dazu beitragen können, einige Vorgänge zu reduzieren (und festzustellen, welche Indizes die besten sind), aber es ist schwer zu sagen, ohne den Ausführungsplan oder die Indizes zu betrachten.
quelle