PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Perché la query più naturale (cioè usando INNER JOIN (invece di LEFT JOIN)) è molto lenta

(come indicato, inserisco parte del mio commento in una risposta poiché ha risolto il problema)

Converti le espressioni EXISTS in espressioni IN.

Funziona meglio in questo caso perché la query verrà ora valutata in modo efficace dall'"interno verso l'esterno" a partire dalla query che contiene il fattore più limitante:la ricerca di testo completo. Quella query restituirà un piccolo insieme di righe che possono essere cercate direttamente sulla chiave primaria della query esterna (WHERE x in (SELECT X...)) invece di chiamare la query "interna" una volta per valore di la query esterna (o per tutti i valori nel tuo caso originale, se lo sto leggendo correttamente). Il metodo EXISTS qui si traduce in cicli annidati (una valutazione di una query per ogni valore in un altro) rispetto al metodo IN che utilizza hash join (un metodo di esecuzione molto più efficiente in molti, se non nella maggior parte, dei casi.

Si noti che con il metodo EXISTS, ci sono quattro cicli nidificati che vengono eseguiti ciascuno almeno 3.000 volte. Quel costo si somma. Sebbene non sia un confronto diretto, puoi trattare i loop nidificati come faresti con i loop FOR nel codice dell'applicazione:ogni volta che invochi un ciclo interno, la tua stima di O grande sale di un ordine di grandezza:da O(n) a O(n^ 2) a O(n^3), ecc.

Hash Join è più simile a una mappa, in cui due array vengono passati contemporaneamente e un'operazione viene eseguita su entrambi. Questo è approssimativamente lineare (O(n)). Pensa a questi nidificati come additivi, quindi andrebbe da O(n) a O(2n) a O(3n), ecc.

Sì, sì, lo so che non è proprio la stessa cosa, ma il punto è che avere più loop nidificati di solito indica un piano di query lento e il confronto dei due stili big-O lo rende più facile da riconoscere, credo.

I cicli annidati e gli EXISTS non sono malvagi, di per sé, ma per la maggior parte dei casi in cui esiste una condizione di filtro di base che alla fine influisce su tutto (ad esempio, la ricerca del testo completo nella domanda), un'espressione IN (o, in alcuni casi, una corretta JOIN) produce un piano molto più efficiente.