Operazione fisica di concatenazione: garantisce l'ordine di esecuzione?


12

In SQL standard, il risultato di a union allnon è garantito in alcun ordine. Quindi, qualcosa del tipo:

select 'A' as c union all select 'B'

Potrebbe restituire due righe in qualsiasi ordine (anche se, in pratica su qualsiasi database che conosco, "A" verrà prima di "B").

In SQL Server, questo si trasforma in un piano di esecuzione usando un'operazione fisica di "concatenazione".

Potrei facilmente immaginare che l'operazione di concatenazione scansionerebbe i suoi input, restituendo qualsiasi input abbia record disponibili. Tuttavia, ho trovato la seguente dichiarazione sul web ( qui ):

Il processore di query eseguirà questo piano nell'ordine in cui gli operatori compaiono nel piano, il primo è il primo e l'ultimo è quello finale.

Domanda: è vero in pratica? Questo è garantito per essere vero?

Non ho trovato alcun riferimento nella documentazione di Microsoft secondo cui gli input sono stati scansionati in ordine, dal primo all'ultimo. D'altra parte, ogni volta che provo a eseguirlo, i risultati suggeriscono che gli input sono, in effetti, elaborati in ordine.

C'è un modo per fare in modo che il motore elabori più di un input alla volta? I miei test (usando espressioni molto più complicate delle costanti) sono su una macchina a 8 core abilitata per parallelo e la maggior parte delle query sfrutta il parallelismo.

Risposte:


10

No , non esiste documentazione di Microsoft che garantisca il comportamento, quindi non è garantita .

Inoltre, supponendo che l'articolo di Simple Talk sia corretto e che l'operatore fisico di concatenazione elabori sempre gli input nell'ordine mostrato nel piano (molto probabilmente per essere vero), quindi senza una garanzia che SQL Server genererà sempre piani che mantengono lo stesso l'ordine tra il testo della query e il piano di query, stai solo leggermente meglio.

Possiamo approfondire ulteriormente questo però. Se Query Optimizer è stato in grado di riordinare l'input dell'operatore di concatenazione, dovrebbero esistere righe nel DMV non documentato, sys.dm_exec_query_transformation_statscorrispondente a tale ottimizzazione.

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

In SQL Server 2012 Enterprise Edition, questo produce 24 righe. Ignorando le false corrispondenze per le trasformazioni correlate alle costanti, esiste una trasformazione relativa all'operatore fisico di concatenazione UNIAtoCON(Unione tutta alla concatenazione). Pertanto, a livello di operatore fisico, sembra che una volta selezionato un operatore di concatenazione, questo verrà elaborato nell'ordine dell'unione logica Tutto l'operatore da cui è stato derivato.


In realtà non è del tutto vero. Esistono riscritture post-ottimizzazione che possono riordinare gli input a un operatore di concatenazione fisico dopo il completamento dell'ottimizzazione basata sui costi. Un esempio si verifica quando la concatenazione è soggetta a un obiettivo di riga (quindi potrebbe essere importante leggere prima dall'input più economico). Vedi UNION ALLOttimizzazione di Paul White per maggiori dettagli.

Quella riscrittura fisica tardiva era funzionale fino a SQL Server 2008 R2 incluso, ma una regressione significava che non si applicava più a SQL Server 2012 e versioni successive. È stata emessa una correzione che ripristina questa riscrittura per SQL Server 2014 e versioni successive (non 2012) con gli aggiornamenti rapidi di Query Optimizer abilitati (ad es. Flag di traccia 4199).


Ma per quanto riguarda l'operatore Logical Union All ( UNIA)? C'è una UNIAReorderInputstrasformazione, che può riordinare gli input. Esistono anche due operatori fisici che possono essere utilizzati per implementare un'unione Tutti logica UNIAtoCONe UNIAtoMERGE(Unione tutti per unire unione).

Pertanto sembra che Query Optimizer possa riordinare gli input per a UNION ALL; tuttavia, non sembra essere una trasformazione comune (zero utilizzi UNIAReorderInputssui server SQL di cui ho prontamente accessibile. Non conosciamo le circostanze che farebbero uso dell'ottimizzatore UNIAReorderInputs; sebbene sia certamente usato quando una guida del piano o l'uso il suggerimento piano viene utilizzato per forzare un piano generato utilizzando gli input riordinati fisici dell'obiettivo di riga sopra menzionati.

C'è un modo per fare in modo che il motore elabori più di un input alla volta?

L'operatore fisico di concatenazione può esistere all'interno di una sezione parallela di un piano. Con qualche difficoltà, sono stato in grado di produrre un piano con concatenazioni parallele utilizzando la seguente query:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

Quindi, nel senso più stretto, l'operatore di concatenazione fisica sembra elaborare sempre gli input in modo coerente (primo in alto, secondo in basso); tuttavia, l'ottimizzatore potrebbe cambiare l'ordine degli input prima di scegliere l'operatore fisico o utilizzare un'unione di unione anziché una concatenazione.


8

Secondo Craig Freedman l'ordine di esecuzione per l'operatore di concatenazione è garantito.

Dal suo post sul blog Visualizzazione dei piani di query sui blog MSDN:

Si noti che quando un operatore ha più di un figlio, l'ordine dei figli è importante. Il figlio più in alto è il primo figlio mentre il figlio più in basso è il secondo. L'operatore di concatenazione elabora i bambini in questo ordine.

E dai libri online Showplan Riferimenti operatori logici e fisici

L'operatore fisico di concatenazione ha due o più input e un output. La concatenazione copia le righe dal primo flusso di input al flusso di output, quindi ripete questa operazione per ciascun flusso di input aggiuntivo.


Quella citazione è abbastanza vicino a quello che stavo cercando. Sono disposto a fare il salto dall'esecuzione in quell'ordine alla restituzione in quell'ordine - sebbene sia deludente che la documentazione precluda l'elaborazione parallela in questo caso.
Gordon Linoff,

2

Risposta wiki della community :

Non so se è possibile dimostrare che qualsiasi comportamento osservato è sempre garantito, in un modo o nell'altro, a meno che non sia possibile produrre un contro-esempio. In mancanza di ciò, il modo per correggere l'ordine in cui i risultati vengono restituiti, ovviamente, è aggiungere un ORDER BY.

Non so se esiste una "correzione" o se esiste una necessità per una correzione, se è possibile dimostrare che in alcuni scenari le query vengono elaborate in un ordine diverso.

La mancanza di una documentazione ufficiale esplicita mi suggerisce che non dovresti dipendere da questo. Questo è esattamente il tipo di cosa con cui le persone hanno avuto problemi ORDER BYin vista e GROUP BYsenza ORDER BY, 8 anni fa, quando è stato rilasciato l'ottimizzatore di SQL Server 2005.

Con tutte le nuove funzionalità delle versioni più recenti di SQL Server (con altre in arrivo), anche se pensi di poter garantire un comportamento specifico oggi, non mi aspetterei che sia vero (fino a quando non sarà documentato).

Anche se non dipendi da questo comportamento, che cosa hai intenzione di fare con i risultati? Ad ogni modo, non chiamerei un articolo di Simple Talk da un funzionario esterno . Per quanto ne sappiamo, questa è solo un'ipotesi basata sull'osservazione.

Microsoft non pubblicherà mai la documentazione ufficiale dicendo che "x" non è garantito per fare "y". Questo è uno dei motivi per cui ancora, quasi un decennio dopo, abbiamo difficoltà a convincere le persone che non possono fare affidamento sugli ordini osservati senza ORDER BY- non esiste documentazione che affermi "non è garantito".

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.