sql >> Database >  >> RDS >> PostgreSQL

Waarom de meest natuurlijke zoekopdracht (d.w.z. INNER JOIN gebruiken (in plaats van LEFT JOIN)) erg traag is

(zoals aangegeven, plaats ik een deel van mijn opmerking in een antwoord omdat het het probleem heeft opgelost)

Converteer de EXISTS-expressies naar IN-expressies.

Dit werkt in dit geval beter omdat de zoekopdracht nu effectief van "binnenstebuiten" wordt geëvalueerd, te beginnen met de zoekopdracht die uw meest beperkende factor bevat:de zoekopdracht voor volledige tekst. Die query retourneert een kleine set rijen die direct kunnen worden opgezocht tegen de primaire sleutel van de buitenste query (WHERE x in (SELECT X...)) in plaats van de "innerlijke" query eenmaal per waarde van de buitenste query (of voor alle waarden in uw oorspronkelijke geval, als ik het goed lees). De EXISTS-methode resulteert hier in geneste lussen (één evaluatie van de ene query voor elke waarde in een andere) versus de IN-methode die hash-joins gebruikt (een veel efficiëntere uitvoeringsmethode in veel, zo niet de meeste gevallen.

Merk op dat er met de EXISTS-methode vier geneste lussen zijn die elk minstens 3.000 keer worden uitgevoerd. Die kosten lopen op. Hoewel het geen directe vergelijking is, kun je geneste lussen behandelen zoals je zou doen met FOR-lussen in applicatiecode:elke keer dat je een binnenste lus aanroept, gaat je big-O-schatting een orde van grootte omhoog:O(n) tot O(n^) 2) tot O(n^3), enz.

Hash Join lijkt meer op een kaart, waar twee arrays tegelijkertijd worden doorlopen en een bewerking op beide wordt uitgevoerd. Dit is ongeveer lineair (O(n)). Denk eraan dat deze als additief worden genest, zodat het van O(n) naar O(2n) naar O(3n) gaat, enz.

Ja, ja, ik weet dat het niet helemaal hetzelfde is, maar het punt is dat het hebben van meerdere geneste lussen meestal wijst op een traag zoekplan en het vergelijken van de twee big-O-stijlen maakt het gemakkelijker te herkennen, geloof ik. em>

Geneste lussen en EXISTS zijn niet per se slecht, maar in de meeste gevallen waar er een basisfiltervoorwaarde is die uiteindelijk alles beïnvloedt (bijvoorbeeld de volledige tekstzoekopdracht in de vraag), een IN-uitdrukking (of, in sommige gevallen, een goede JOIN) levert een veel efficiënter plan op.



  1. ORA-00904::ongeldige id Oracle sql

  2. MySQL-back-up met WHERE-voorwaarde

  3. Hoe voorwaarden te controleren en tekst in orakelformulieren voor tekstbestanden te schrijven

  4. De resultaten van meerdere SQL-selecties toevoegen?