sql >> Databáze >  >> RDS >> PostgreSQL

Proč je nejpřirozenější dotaz (tj. použití INNER JOIN (místo LEFT JOIN)) velmi pomalý

(podle pokynů vkládám část svého komentáře do odpovědi, protože problém vyřešil)

Převeďte EXISTS výrazy na výrazy IN.

V tomto případě to funguje lépe, protože dotaz bude nyní efektivně vyhodnocen „zevnitř“, počínaje dotazem, který obsahuje váš nejvíce omezující faktor:vyhledávání fulltextového vyhledávání. Tento dotaz vrátí malou sadu řádků, které lze vyhledat přímo proti primárnímu klíči vnějšího dotazu (WHERE x in (SELECT X...)), na rozdíl od volání „vnitřního“ dotazu jednou za hodnotu vnější dotaz (nebo pro všechny hodnoty ve vašem původním případě, pokud to čtu správně). Metoda EXISTS zde vede k Nested Loops (jedno vyhodnocení jednoho dotazu pro každou hodnotu v jiné) oproti metodě IN využívající Hash Joins (mnohem efektivnější způsob provádění v mnoha, ne-li ve většině případů).

Všimněte si, že u metody EXISTS existují čtyři vnořené smyčky, které se spouštějí, přičemž každá běží alespoň 3000krát. Ta cena se sčítá. I když se nejedná o přímé srovnání, můžete s vnořenými smyčkami zacházet jako se smyčkami FOR v kódu aplikace:pokaždé, když vyvoláte vnitřní smyčku, váš odhad big-O se zvýší o řád:O(n) až O(n^ 2) na O(n^3) atd.

Hash Join je spíše mapa, kde se procházejí dvě pole současně a na obou se provádí operace. Toto je zhruba lineární (O(n)). Představte si, že jsou vnořené jako aditivní, takže by to šlo O(n) až O(2n) až O(3n) atd.

Ano, ano, vím, že to není úplně totéž, ale jde o to, že více vnořených smyček obvykle znamená pomalý plán dotazů a porovnání dvou stylů velkých O je podle mě snazší rozpoznat. em>

Vnořené smyčky a EXISTUJE nejsou samy o sobě zlé, ale pro většinu případů, kdy existuje podmínka základního filtru, která nakonec ovlivňuje vše (například fulltextové vyhledávání v otázce), výraz IN (nebo v některých správné JOIN) přináší mnohem efektivnější plán.



  1. vypočítat součet hodnot spojených s překrývajícími se obdobími

  2. PIVOT dotaz na odlišné záznamy

  3. Porovnání dvou období v rámci stejné tabulky

  4. Sloupec MySQL nastaven na NOT NULL, ale stále umožňuje hodnoty NULL