Nessun vantaggio derivante dall'utilizzo di Cross Apply o CTE rispetto alla sottoquery in linea
-
28-09-2020 - |
Domanda
Mi sono imbattuto in una query come questa:
SELECT (SELECT COUNT(1) FROM Orders o WHERE i.ItemId = o.ItemId) [C]
FROM Items i
L'ho cambiato in seguito
;WITH cte_count
AS
(
SELECT COUNT(1) c, OrderId FROM Orders Group By ItemId
)
SELECT a.c [Count], i.Name
FROM Items i
INNER JOIN cte_count c ON (c.ItemId = i.ItemId)
Ma il piano di esecuzione per entrambi è lo stesso mostrato di seguito:
Allo stesso modo è stata selezionata un'altra query TOP 1 Order By Id
.Ho provato a spostare questo in CROSS APPLY
Ma anche per questo ho ottenuto gli stessi piani di esecuzione.
Ovviamente c'erano altri join e colonne nella query.
Il mio dilemma riguarda l'utilità e i vantaggi dell'utilizzo CROSS APPLY
E CTE
.Ce ne sono o sono semplicemente esotici?
Soluzione
Ma il piano di esecuzione per entrambi è lo stesso mostrato di seguito:
I piani sono diversi.Uno è un inner join, l'altro è un external join.I risultati potrebbero essere gli stessi nel tuo semplice test, ma la semantica è diversa.Nelle query più complesse, la differenza può causare piani di esecuzione più ovviamente diversi e avere un impatto sulle prestazioni.
Di solito esistono molti modi per esprimere lo stesso requisito (o requisito simile, come nel tuo esempio) in SQL.Quello che usi è inizialmente una questione di preferenze e stile.In alcuni casi, l'utilizzo dell'uno o dell'altro produrrà importanti differenze di prestazioni perché l'SQL dichiarativo segue un percorso di codice diverso attraverso l'ottimizzatore.In questo caso particolare, l'outer join potrebbe funzionare meno bene con le capacità di esplorazione dell'ottimizzatore (ha meno strumenti da utilizzare con gli outside join rispetto agli inner join).
Riscrivere una query per definire il file Stesso i risultati che utilizzano una sintassi diversa possono rappresentare un metodo di ottimizzazione valido, ma richiede un'attenzione particolare ai dettagli e un nuovo test ogni volta che SQL Server viene aggiornato o aggiornato.Generalmente non c'è motivo di preferire un modo di esprimere un requisito in SQL rispetto a un altro.
Inoltre, come menzionato da Andriy in a commento sull'altra copia della tua domanda, "nel caso più generale, le tue query in linea ti daranno solo un risultato per riga, mentre si uniscono a un CTE (che non deve essere un CTE, potrebbe essere una normale sottoselezione) o l'APPLICAZIONE INCROCIATA di un set di righe può darti accesso a più di una colonna."
Altri suggerimenti
Il mio dilemma riguarda l'utilità e i vantaggi dell'utilizzo di CROSS APPLY e CTE.Ce ne sono o sono semplicemente esotici?
Per set di dati di piccole dimensioni l'ottimizzatore probabilmente non si preoccupa di un'analisi approfondita.Tuttavia, se si dovessero esaminare piani concorrenti per set di dati di grandi dimensioni (ad esempio milioni di ordini o articoli dal tuo esempio), allora CROSS APPLY, soprattutto se gli articoli sono indicizzati, verrebbe eseguito più rapidamente.
Inoltre è opportuno verificarlo in questo modo, utilizzando il piano di esecuzione.
Sicuro.Se ci fosse stata una differenza, i piani lo avrebbero dimostrato.Inoltre noterai sicuramente differenze di prestazioni durante l'esecuzione.
E se lo facessi?
SELECT i.Name
COUNT(o.OrderId) c
FROM Items i
JOIN Orders o ON i.ItemID = o.ItemID
GROUP BY i.ItemID
cte
E apply
in alcuni casi ha i suoi vantaggi, ne sono sicuro, ma probabilmente non sono casi semplici come questo
Mi piace usare a cte
principalmente per ragioni estetiche quando cerco di creare un flusso visivo di come suddivido i risultati più grandi in risultati più piccoli, per costruire la query finale e ovviamente la ricorsione.
apply
è piuttosto interessante quando usi una funzione di valore di tabella che prende un valore param dalla tabella precedente. cross apply
può essere più carino di a full join
dichiarazione.
se sai cosa stai cercando in un piano di query, suppongo sia solo una questione di preferenza