Quando utilizzare le sottoquery SQL rispetto a un join standard?

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.

Qualsiasi aiuto sarebbe apprezzato.

Le sottoquery di solito sono soddisfacenti a meno che non siano sottoquery dipendenti (note anche sottoquery correlate ). Se si utilizzano solo sottoquery indipendenti e stanno utilizzando indici appropriati, dovrebbero essere eseguiti rapidamente. Se si dispone di una sottoquery dipendente, è ansible 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 sei sicuro di cosa si intenda per dipendenza o indipendenza da una sottoquery, ecco una regola generale: se puoi prendere la sottoquery, rimuoverla dal suo contesto, eseguirla e ottenere un set di risultati, allora è una independent subquery .

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

La regola generale ha alcune eccezioni. Per esempio:

  • Molti ottimizzatori possono prendere una subquery dipendente e trovare un modo per eseguirla 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 è identificata erroneamente come una 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 te.

Non c’è nessun proiettile d’argento qui. Ogni utilizzo deve essere valutato in modo indipendente. Ci sono alcuni casi in cui le subquery correlate sono semplici inefficienti, questa sotto è meglio scritta come una JOIN

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

D’altra parte, le query EXISTS e NOT EXISTS vinceranno su JOINs.

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

È normalmente più veloce di

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

Tuttavia, anche queste generalizzazioni possono essere false per ogni particolare schema e distribuzione dei dati.

Sfortunatamente la risposta dipende molto dal server SQL che stai 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.