Ho una doppia query self-join in cui le prestazioni sono gravemente ridotte quando i valori di ricerca vengono scambiati.Le prestazioni query SQL diminuiscono in base all'ordine dei valori di ricerca
-- 500,000 i/o & 500ms execution
select
fooA.ID
, fooB.ID
from
foo AS fooA
INNER JOIN bar AS barA ON fooA.barID = barA.barID
INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join
INNER JOIN bar AS barB ON fooB.barID = barB.barID
where
barA.value = 'xyz'
AND barB.value = '60'
-- 5,000 i/o & 5ms execution
select
fooA.ID
, fooB.ID
from
foo AS fooA
INNER JOIN bar AS barA ON fooA.barID = barA.barID
INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join
INNER JOIN bar AS barB ON fooB.barID = barB.barID
where
barA.value = '60'
AND barB.value = 'xyz'
- Il valore "xyz" è elencato 150.000 volte nella tabella "bar".
- Il valore "60" è elencato 500 volte nella tabella "bar".
- I piani di query sono uguali, tranne per il fatto che il ciclo più interno restituisce 150.000 righe o 500 righe a seconda del valore di ricerca elencato per primo.
- Le ricerche eseguono ricerche su indici non in cluster.
- Le statistiche sono state aggiornate su entrambe le tabelle con FULLSCAN.
Perché l'ottimizzatore di query SQL non identifica correttamente che in entrambi i casi il join interno del piano di query deve essere quello con il minor numero di righe?
Utilizzare i criteri che limita il numero di righe nella query per primo sempre. È una regola generale. – JonH
Risposta possibile: parametrizzazione delle query, snifing dei parametri e riutilizzo dei piani. –
Puoi fare le chiavi primarie ids sulle tabelle foo e bar? –