Puzzle di Query Optimizer di SQL Server 2008 R2
Abbiamo due tabelle, entrambe contenenti 9 milioni di righe. 70.000 righe sono diverse, le altre sono uguali.
Questo è veloce, 13 secondi,
select * from bigtable1
except select * from similar_bigtable2
Questo ordina l'output ed è anche veloce, anche 13 secondi,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Mentre questo è enormemente lento:
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
E anche un "trucco" che a volte uso per suggerire a SQL Server che deve precalcolare una determinata parte della query prima che passi, non funziona e risulta anche in una query lenta:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Osservando i piani di query non è difficile trovare il motivo:
SQL Server posiziona due tipi di 9 milioni di righe prima dell'hashatch, mentre preferirei che avesse aggiunto solo un tipo di 70.000 righe dopo l'hashatch.
Quindi la domanda: come posso istruire Query Optimizer a farlo?
EXCEPT
(ad esempio OUTER JOIN
)? Mi rendo conto che la sintassi è meno conveniente, ma potresti essere in grado di giocare meglio con i suggerimenti di indice / join (o potresti non averne bisogno). L'alternativa che stai utilizzando ora (inserendo prima una tabella #temp) è un'ultima soluzione alternativa, ma in alcuni casi è l'unico modo per forzare l'ottimizzatore a separare completamente due parti di una query nel modo desiderato.