sql >> Database >  >> RDS >> PostgreSQL

Wanneer zijn (SELECT) queries gepland?

Ik kan niet praten over de Perl-interface aan de clientzijde zelf, maar ik kan wat licht werpen op de PostgreSQL-server.

PostgreSQL heeft verklaringen opgesteld en onvoorbereide verklaringen. Onvoorbereide verklaringen worden onmiddellijk ontleed, gepland en uitgevoerd. Ze doen ook niet ondersteuning parametervervanging. Op een gewone psql shell kun je hun zoekplan als volgt tonen:

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

Aan de andere kant zijn er voorbereide statements:Ze worden meestal (zie "uitzondering" hieronder) ontleed en gepland in één stap en uitgevoerd in een tweede stap. Ze kunnen meerdere keren opnieuw worden uitgevoerd met verschillende parameters, omdat ze doen ondersteuning parametervervanging. Het equivalent in psql is dit:

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

U ziet misschien dat het plan verschilt van het plan in de onvoorbereide verklaring, omdat de planning al plaatsvond in de prepare fase zoals beschreven in het document voor PREPARE :

Dit betekent ook dat het plan NIET . is geoptimaliseerd voor de vervangen parameters:in de eerste voorbeelden zou een index kunnen worden gebruikt voor flag omdat PostgreSQL weet dat binnen een miljoen ingangen slechts tien de waarde true hebben . Deze redenering is onmogelijk wanneer PostgreSQL een voorbereide verklaring gebruikt. In dat geval wordt een plan gemaakt dat voor alle mogelijke parameterwaarden zo goed mogelijk werkt. Dit misschien sluit de genoemde index uit omdat het ophalen van het grootste deel van de volledige tabel via willekeurige toegang (vanwege de index) langzamer is dan een gewone sequentiële scan. De VOORBEREIDEN doc bevestigt dit:

BTW - Betreffende het cachen van plannen de PREPARE doc heeft ook iets te zeggen:

Er is ook geen automatische caching van plannen en geen caching/hergebruik over meerdere verbindingen.

UITZONDERING :Ik heb "meestal" genoemd. De getoonde psql voorbeelden zijn niet de dingen die een clientadapter zoals Perl DBI echt gebruikt. Het gebruikt een bepaald protocol . Hier komt de term "eenvoudige zoekopdracht" overeen met de "onvoorbereide zoekopdracht" in psql , de term "uitgebreide zoekopdracht " komt overeen met "voorbereide zoekopdracht" met één uitzondering:er is een onderscheid tussen (één) "naamloze verklaring" en (mogelijk meerdere) "benoemde verklaringen". Met betrekking tot benoemde verklaringen de doc zegt:

en ook:

Dus in dit geval wordt de planning gedaan zonder parameters zoals hierboven beschreven voor PREPARE - niets nieuws.

De genoemde uitzondering is de "naamloze verklaring". De doc zegt:

En hier is het voordeel:hoewel de naamloze verklaring "voorbereid" is (d.w.z. parametervervanging kan hebben), kan deze ook het queryplan aanpassen aan de daadwerkelijke parameters.

BTW:De exacte afhandeling van de naamloze instructie is meerdere keren gewijzigd in de afgelopen releases van de PostgreSQL-server. Je kunt de oude documenten opzoeken voor details als je dat echt wilt.

Rationale - Perl / elke klant :

Hoe een klant zoals Perl het protocol gebruikt, is een heel andere vraag. Sommige clients houden van het JDBC-stuurprogramma voor Java zeggen in feite:zelfs als de programmeur een voorbereide instructie gebruikt, worden de eerste vijf (of zo) uitvoeringen intern toegewezen aan een "eenvoudige query" (d.w.z. in feite onvoorbereid), daarna schakelt het stuurprogramma over naar " benoemde verklaring".

Een klant heeft dus de volgende keuzes:

  • Dwing (her)planning elke keer af met behulp van het "simple query"-protocol.
  • Plan eenmaal, voer meerdere keren uit met behulp van het "extended query"-protocol en de "named statement" (plan kan slecht zijn omdat planning zonder parameters wordt gedaan).
  • Ontcijferen plan een keer voor elke uitvoering (met de huidige PostgreSQL-versie) door het "extended query" -protocol en de "naamloze instructie" te gebruiken en nog meer dingen te gehoorzamen (geef enkele parameters op tijdens het "parse" -bericht)
  • Speel totaal andere trucs zoals de JDBC-driver.

Wat Perl momenteel doet:ik weet het niet. Maar de genoemde "rode haring" is niet erg onwaarschijnlijk.




  1. Een lijst krijgen van alle kolomnamen in een tabel die geen NULL als standaardwaarde hebben?

  2. docker SHM_SIZE /dev/shm:formaat van gedeeld geheugen wijzigen

  3. Hoe pl/sql-uitzondering opnieuw te verhogen in het blok voor het afhandelen van uitzonderingen?

  4. VARCHAR(MAX) versus VARCHAR(n) in Oracle