2012-05-15 13 views
5

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?

+0

Utilizzare i criteri che limita il numero di righe nella query per primo sempre. È una regola generale. – JonH

+1

Risposta possibile: parametrizzazione delle query, snifing dei parametri e riutilizzo dei piani. –

+0

Puoi fare le chiavi primarie ids sulle tabelle foo e bar? –

risposta

3

SQL Server non ricompila una query ogni volta che viene eseguita. Lo fa una volta, e ottimizzato per i valori esatti che vede la prima volta. Immagino tu abbia messo in cache un piano sfortunato.

Prova ad aggiungere OPTION (RECOMPILE) alla fine.

+0

Ho aggiunto questo e non ci sono stati cambiamenti. Il numero stimato di righe dall'unione più interna è 2.500 per entrambi i piani di query, ma l'effettivo è ampiamente diverso. –

+0

Questo è strano. La stima della cardinalità sugli indici per la corrispondenza di uguaglianza è solitamente molto accurata. Le tabelle che stai cercando contengono un numero molto elevato di righe con pochissimi duplicati? – usr

+0

Non riesco davvero a vedere nulla che possa causare problemi qui. Puoi pubblicare screenshot dei due piani di esecuzione effettivi? – usr