2011-01-25 11 views
26

Sto lavorando per riscrivere alcune query SQL scritte male e stanno sfruttando eccessivamente le sottoquery. Sto cercando le migliori pratiche riguardanti l'uso di sottoquery.Quando utilizzare le sottoquery SQL rispetto a un join standard?

Qualsiasi aiuto sarebbe apprezzato.

+0

Non è che non ci sia un proiettile d'argento - il problema è che la domanda è troppo ampia per essere ragionevolmente risolta.Non c'è alcuna garanzia che ciò che funziona su un database (MySQL), funzioni esattamente allo stesso modo su un altro. La regola più semplice è che se le colonne della subquery si trovano nel set di risultati finale, utilizzare un JOIN: è il metodo più ottimale per ottenere i dati da due tabelle. Altrimenti, una sottoquery va bene, ma quelle correlate possono causare problemi (anche se non con EXISTS). –

+1

Su quale base si afferma che le sottoquery sono state sovrasfruttate? Sembra strano decidere che _e quindi_ chiedere informazioni sulle migliori pratiche per l'utilizzo delle sottocommissioni. –

+1

Possibile duplicato di [Join vs sub-query] (http://stackoverflow.com/questions/2577174/join-vs-sub-query) –

risposta

39

Le sottoquery di solito sono soddisfacenti a meno che non siano subquery dipendenti (noto anche come correlated subqueries). Se si utilizzano solo sottoquery indipendenti e stanno utilizzando indici appropriati, dovrebbero essere eseguiti rapidamente. Se si dispone di una sottoquery dipendente, è possibile che si verifichino problemi di prestazioni, poiché in genere una subquery dipendente deve essere eseguita una volta per ogni riga nella query esterna. Quindi se la query esterna ha 1000 righe, la sottoquery verrà eseguita 1000 volte. D'altra parte una subquery indipendente in genere deve essere valutata solo una volta.

Se non si è sicuri di cosa significhi una subquery dipendente o indipendente, ecco una regola generale: se si può prendere la sottoquery, rimuoverla dal suo contesto, eseguirla e ottenere un set di risultati, quindi è un independent subquery.

Se si verifica un errore di sintassi poiché si riferisce ad alcune tabelle esterne alla sottoquery, si tratta di un dependent subquery.

La regola generale prevede alcune eccezioni. Ad esempio:

  • Molti ottimizzatori possono richiedere una sottoquery dipendente e trovare un modo per eseguirlo in modo efficiente come un JOIN. Ad esempio, una query NOT EXISTS potrebbe risultare in un piano di query ANTI JOIN, quindi non sarà necessariamente più lento della scrittura della query con un JOIN.
  • MySQL ha un bug in cui una sottoquery indipendente all'interno di un'espressione IN viene erroneamente identificata come subquery dipendente e quindi viene utilizzato un piano di query non ottimale. Questo è apparentemente risolto nelle versioni più recenti di MySQL.

Se le prestazioni sono un problema, misurare le query specifiche e vedere cosa funziona meglio per voi.

+0

Per correlazione intendi contenere un riferimento a una colonna nella query esterna? –

+0

@El Ronnoco: Sì –

+3

"Molti ottimizzatori possono richiedere una sottoquery dipendente e trovare un modo per eseguirlo in modo efficiente" - Sono d'accordo con questa affermazione e nega l'intero argomento, ad esempio "Le sottoquery correlate sono errate tranne quando non sono negative" . – onedaywhen

4

Sfortunatamente la risposta dipende molto dal server SQL che si sta utilizzando. In teoria, le unioni sono migliori da un punto di vista della teoria relazionale pura. Lasciano che il server faccia la cosa giusta sotto il cofano e gli dia più controllo e quindi alla fine può essere più veloce. Se il server è implementato correttamente. In pratica, alcuni server SQL hanno prestazioni migliori se li ingannano nell'ottimizzare le sue query tramite sottoquery e simili.

+0

Alcune sottocroche possono anche essere promosse a join (server-dipendente, di corso). Per la maggior parte dei casi trovo che le unioni "si adattino alla mia testa" siano migliori. –

+0

No, se un server viene implementato correttamente, riconoscerà il modo più veloce per eseguire un JOIN o una sottoquery e produrre il piano di esecuzione ottimale. Se il JOIN e la sotto-query sono algebricamente uguali, allora un server ben implementato produrrà lo stesso piano di esecuzione. –

+0

Sì ... Tutto vero. Se un server viene implementato alla perfezione ottimizzerà sempre anche le query interrotte ;-) Ma ... questo era il mio punto principale: quasi tutti i server sql funzionano meglio se costruisci le tue query in base a come si comporta. È una sfortunata verità. In genere, più un prodotto è lungo e più è probabile che svolga un lavoro migliore, indipendentemente dalla struttura delle query. Ma anche questo non è sempre vero. –

5

Non c'è nessun proiettile d'argento qui. Ogni utilizzo deve essere valutato in modo indipendente. Ci sono alcuni casi in cui subquery correlate sono chiare inefficienti, questo qui sotto è meglio scritto come un ENTRA

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc) 
from users u 

D'altra parte, esiste e non EXISTS query vinceranno fuori sopra join.

select ... 
where NOT EXISTS (.....) 

è normalmente più veloce di

select ... 
FROM A LEFT JOIN B 
where B.ID is null 

Eppure anche queste generalizzazioni può essere falso per qualsiasi schema particolare e la distribuzione dei dati.

+3

... e RDBMS :-) –

Problemi correlati