Prestazioni CTE ricorsive


8

Hai bisogno di aiuto con le prestazioni CTE ricorsive. Sotto CTE sta funzionando molto lentamente mentre sta cercando di estrarre i dati gerarchici in modo ricusivo. La tabella è grande con ogni ID root con fino a 3 itemid ricorsivi. Potrebbero esserci circa 200000 o più ID root. So che i CTE ricorsivi sono lenti per enormi set di dati poiché per ogni rootid in anchor sarebbe itemid ricorsivamente.

Schema:

Create table RootItem (ItemId int primary key, RootIt int , insertdate datetime)

La tabella sopra ha più di 1 milione di righe.

Query 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
)

Non possiamo modificare lo schema delle tabelle e usare heirarchyid. Ho provato anche in loop ma anche quello è lento.

Esiste un altro modo per ottimizzare questa query?

 ; 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' 

Sto anche lavorando con il gruppo BI per modificare la logica delle query e filtrare i dati nel cte stesso di spostare un paio di join e criteri in cte .. Grazie per tutti i commenti.


2
perché hai bisogno di tutte le gerarchie? Non dovrebbe esserci un posto dove chissà dove, quindi devi solo iscriverti per i record che intendi usare. Sicuramente non è necessario creare milioni di gerarchie ogni volta che si esegue questo.
HLGEM,

Questo è un rapporto collaterale che viene eseguito circa 5-6 volte in un orario lavorativo e deve essere eseguito su un intero set di dati. Avrei potuto precaricare i dati se i dati fossero statici o non inseriti spesso ma in questo caso frequenti operazioni DML sono in esecuzione su questa tabella nel DB.
njvds,

Quali indici hai a questa tabella?
ypercubeᵀᴹ

ItemID è la chiave primaria e c'è anche un indice non cluster su itemid e rootid.
njvds,

1
Devi mostrare la query che stai effettivamente utilizzando. Come è ora, tutto ciò che fai è un modo complicato di restituire tutto ItemID dalla tabella. Il CTE ricorsivo non aggiunge alcun valore.
Mikael Eriksson il

Risposte:


3

Dici che la gerarchia viene modificata. Presumibilmente mentre questa operazione è in esecuzione, c'è una certa quantità di blocco che sta avvenendo allora?

Anche se la gerarchia sta cambiando, stanno cambiando le radici degli oggetti?

Hai guardato il tempo necessario per creare la tabella di mapping da root a elemento e indicizzarla?

Mi piacerebbe vedere il piano di esecuzione per vedere cosa sta succedendo - il CTE dovrebbe essere spooling, ma come tabella materializzata e indicizzata manualmente potrebbe funzionare meglio nei passaggi successivi.

Anche con attività pesanti, mi sembra che qualcuno debba essere bloccato se le operazioni DML stanno modificando i dati che questo processo sta leggendo.

Quindi prenderei fortemente in considerazione di scattare un'istantanea della gerarchia.

Inoltre, hai un certo numero di altri JOIN INNER: dovresti verificare se sono effettivamente i CTE e se mancano degli indici per rendere effettivi quei join. Il piano di esecuzione dovrebbe dirtelo.

Sembra che ci siano alcune cose nella clausola WHERE che potrebbero aiutare a ridurre alcune operazioni (e determinare quali indici potrebbero essere i migliori)), ma è difficile dirlo senza guardare al piano di esecuzione o agli indici.


Perché un'operazione DML bloccherebbe SELECT? SQL Server è ancora così limitato?
a_horse_with_no_name

@a_horse_with_no_name msdn.microsoft.com/en-us/library/ms173763.aspx~~V~~3rd è possibile, ma l'utente menzionati v'è alta attività, così avrebbe avuto bisogno di prendere in considerazione la sua strategia
Cade Roux
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.