Rekursive CTE-Leistung


8

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.


2
Warum brauchen Sie alle Hierarchien? Sollte es nicht irgendwo eine Where-Clasue geben, so berechnen Sie nur die Datensätze, die Sie verwenden möchten. Sicherlich müssen Sie nicht jedes Mal Millionen von Hierarchien erstellen, wenn Sie dies ausführen.
HLGEM

Dies ist ein Sicherheitenbericht, der in den Geschäftszeiten etwa fünf- bis sechsmal ausgeführt wird und für den gesamten Datensatz ausgeführt werden muss. Ich hätte die Daten vorab laden können, wenn die Daten statisch waren oder nicht oft eingefügt wurden. In diesem Fall werden jedoch häufig DML-Operationen für diese Tabelle in der Datenbank ausgeführt.
NJVDS

Welche Indizes haben Sie an dieser Tabelle?
Ypercubeᵀᴹ

ItemID ist der Primärschlüssel und es gibt auch einen nicht gruppierten Index für itemid und rootid.
NJVDS

1
Sie müssen die Abfrage anzeigen, die Sie tatsächlich verwenden. Alles, was Sie jetzt tun, ist eine komplizierte Methode, um alle ItemIDs aus der Tabelle zurückzugeben. Der rekursive CTE fügt keinen Wert hinzu.
Mikael Eriksson

Antworten:


3

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.


Warum sollte eine DML-Operation SELECT blockieren? Ist SQL Server immer noch so eingeschränkt?
a_horse_with_no_name

@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx es ist möglich, aber der Benutzer erwähnte, dass es eine hohe Aktivität gibt, so dass er seine Strategie überlegen müsste
Cade Roux
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.