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

Kdy se plánují (SELECT) dotazy?

Nemohu mluvit o samotném rozhraní Perlu na straně klienta, ale mohu vnést trochu světla na stranu serveru PostgreSQL.

PostgreSQL má připravené příkazy a nepřipravené příkazy. Nepřipravené příkazy jsou analyzovány, naplánovány a okamžitě provedeny. Také nedělají podpora substituce parametrů. Na prostém psql shell můžete zobrazit jejich plán dotazů takto:

tmpdb> explain select * from sometable where flag = true;

Na druhé straně jsou připravené příkazy:Obvykle se (viz "výjimka" níže) analyzují a plánují v jednom kroku a provádějí ve druhém kroku. Mohou být několikrát znovu spuštěny s různými parametry, protože dělají podpora substituce parametrů. Ekvivalent v psql je toto:

tmpdb> prepare foo as select * from sometable where flag = $1;
tmpdb> explain execute foo(true);

Můžete vidět, že plán se liší od plánu v nepřipraveném prohlášení, protože plánování proběhlo již v prepare fázi, jak je popsáno v dokumentu pro PŘIPRAVIT :

To také znamená, že plán NE optimalizováno pro substituované parametry:V prvních příkladech může být použit index pro flag protože PostgreSQL ví, že z milionu záznamů má pouze deset hodnotu true . Tato úvaha je nemožná, když PostgreSQL používá připravený příkaz. V takovém případě je vytvořen plán, který bude co nejlépe fungovat pro všechny možné hodnoty parametrů. Toto může vyloučit zmíněný index, protože načítání lepší části kompletní tabulky prostřednictvím náhodného přístupu (kvůli indexu) je pomalejší než prosté sekvenční skenování. PŘÍPRAVA doc to potvrzuje:

BTW – Pokud jde o ukládání plánu do mezipaměti, PŘIPARE doc má také co říct:

Také neexistuje žádné automatické ukládání plánu do mezipaměti a žádné ukládání do mezipaměti/opakované použití přes více připojení.

VÝJIMKA :Zmínil jsem „obvykle“. Zobrazený psql příklady nejsou věci, které klientský adaptér jako Perl DBI skutečně používá. Používá určitý protokol . Zde výraz „jednoduchý dotaz“ odpovídá „nepřipravenému dotazu“ v psql , výraz "rozšířený dotaz " odpovídá "připravenému dotazu" s jednou výjimkou:Je rozdíl mezi (jedním) "nepojmenovaným příkazem" a (možná více) "pojmenovanými příkazy". Pokud jde o pojmenované příkazy, doc říká:

a také:

Takže v tomto případě se plánování provádí bez parametrů, jak je popsáno výše pro PREPARE - nic nového.

Zmíněnou výjimkou je „nejmenovaný výrok“. Doktor říká:

A zde je výhoda:Přestože je nepojmenovaný příkaz "připravený" (tj. může mít substituci parametrů), může také přizpůsobit plán dotazů skutečným parametrům.

BTW:Přesné zpracování nepojmenovaného příkazu se v minulých verzích PostgreSQL serveru několikrát změnilo. Pokud opravdu chcete, můžete vyhledat podrobnosti ve starých dokumentech.

Odůvodnění – Perl / libovolný klient :

Jak klient jako Perl používá protokol je úplně jiná otázka. Někteří klienti, jako je ovladač JDBC pro Javu, v podstatě říkají:I když programátor použije připravený příkaz, prvních pět (nebo tak) spuštění je interně mapováno na „jednoduchý dotaz“ (tj. efektivně nepřipravený), poté se ovladač přepne na „ pojmenované prohlášení“.

Klient má tedy tyto možnosti:

  • Vynutit (pře)plánování pokaždé pomocí protokolu „jednoduchého dotazu“.
  • Plánovat jednou proveďte vícekrát pomocí protokolu „extended query“ a „named statement“ (plán může být špatný, protože plánování se provádí bez parametrů).
  • Analyzovat jednou naplánujte každé spuštění (s aktuální verzí PostgreSQL) pomocí protokolu „extended query“ a „unnamed statement“ a dodržujte některé další věci (poskytněte nějaké parametry během zprávy „parse“)
  • Zahrajte si úplně jiné triky, jako je ovladač JDBC.

Co Perl v současnosti dělá:Nevím. Zmíněný „červený sleď“ ale není příliš nepravděpodobný.




  1. Jak vytvořit prázdný/prázdný sloupec s dotazem SELECT v oracle?

  2. Aktualizované možnosti úrovně databáze SQL Azure

  3. Vyberte poddotaz, který vrací více řádků jako řetězec (jeden sloupec) v tabulce (Oracle SQL)

  4. Seskupit MySQL podle a přeskočit seskupování na nulové hodnoty