Ho una query che unisce alcune tabelle ed esegue abbastanza male - le stime delle righe sono lontane (1000 volte) e viene scelto il join di cicli annidati, con il risultato di più scansioni di tabelle. La forma della query è abbastanza semplice, simile a questa:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
Giocando con la query, ho notato che quando suggerisco di utilizzare un join Unisci per uno dei join, viene eseguito molte volte più velocemente. Questo posso capire - Unire join è un'opzione migliore per i dati che vengono uniti, ma SQL Server non lo stima semplicemente scegliendo i loop nidificati.
Quello che non capisco del tutto è perché questo suggerimento di join modifica tutte le stime per tutti gli operatori del piano? Dalla lettura di diversi articoli e libri, ho ipotizzato che le stime della cardinalità fossero eseguite prima della costruzione del piano, quindi l'uso di un suggerimento non avrebbe modificato le stime, ma piuttosto esplicitamente dire a SQL Server di utilizzare una particolare implementazione di join fisico.
Quello che vedo, tuttavia, è che il suggerimento Unisci fa sì che tutte le stime diventino praticamente perfette. Perché questo accade e ci sono tecniche comuni per fare in modo che Query Optimizer effettui una stima migliore senza un suggerimento, considerando che le statistiche ovviamente lo consentono?
UPD: i piani di esecuzione anonimizzati sono disponibili qui: https://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl=0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
Ho controllato le statistiche utilizzate da entrambe le query usando TF 3604, 9292 e 9204, e quelle sono identiche. Tuttavia gli indici che vengono scansionati / ricercati differiscono tra le query.
Oltre a ciò, ho provato a eseguire la query con OPTION (FORCE ORDER)
: funziona ancora più velocemente rispetto all'utilizzo del join unione, scegliendo HASH MATCH per ogni join.