De queryverwerkingsonderdelen identificeren

Voltooid

Er zijn vier afzonderlijke fasen voor het uitvoeren van de query. In de volgorde van uitvoering zijn deze fasen:

  1. Parseren
  2. Transformatie (Herschrijver)
  3. Planning
  4. Uitvoering

De parser

De parser is verantwoordelijk voor het controleren van de querytekenreeks op geldige syntaxis. De parser heeft twee hoofdonderdelen:

  • gram.y die bestaat uit een set grammaticaregels en bijbehorende acties.
  • scan.1 de lexer, waarmee id's en SQL-sleutelwoorden worden herkend. Elk sleutelwoord of elke id activeert een token dat wordt gemaakt en aan de parser wordt overhandigd.

De parser bouwt een querystructuur, waarmee de query wordt gescheiden in identificeerbare onderdelen om te begrijpen welke tabellen erbij betrokken zijn, welke filters zijn toegepast, enzovoort. De onderdelen van een querystructuur zijn:

  • Opdrachttype - SELECT, INSERT, UPDATE of DELETE.
  • Range Table Entry (RTE), een lijst met relaties, ie tabellen, subquery’s, resultaten van joins, enzovoorts. In een SELECT instructie worden deze items weergegeven na het trefwoord FROM.
  • resultaatrelatie: de resultaatrelatie voor opdrachten INSERT, UPDATE en DELETE is de tabel of de view waar de wijzigingen van kracht worden.
  • doellijst: de resultaten van de query, geïdentificeerd tussen de sleutelwoorden SELECT en FROM. Delete-opdrachten produceren geen resultaat, dus de planner voegt een speciale vermelding toe zodat de uitvoerder de rij kan vinden die moet worden verwijderd. Met INSERT-opdrachten worden de nieuwe rijen geïdentificeerd die naar de resultaatrelatie moeten gaan. Voor UPDATE-opdrachten worden in de doellijst de nieuwe rijen beschreven die de oude rijen moeten vervangen.
  • Kwalificatie - een Booleaanse waarde die aangeeft of de bewerking voor de uiteindelijke resultaatrij moet worden uitgevoerd. Deze komt overeen met de WHERE-component van een SQL-instructie.
  • joinboom: deze boom kan een lijst met de FROM items zijn. Joins kunnen in elke volgorde worden uitgevoerd of in een specifieke volgorde, zoals Outer joins.
  • Overige- items die in deze fase niet relevant zijn, zoals de ORDER BY-component.

Herschrijver

De uitvoer van de parser wordt doorgegeven aan de transformatie of rewriter proces, tenzij er een fout wordt gevonden in welk geval een foutbericht wordt geretourneerd.

De query-herschrijffunctie herschrijft de querytekst door regels toe te passen erop. De rewriter houdt rekening met regels en geeft vervolgens de gewijzigde query door aan de queryplanner. Beveiliging op rijniveau wordt in deze fase geïmplementeerd.

Regels voor SELECT worden bijvoorbeeld altijd toegepast als laatste stap, waaronder voor INSERT-, UPDATE- en DELETE-query's. Regels betekenen ook dat UPDATE-query's bestaande rijen niet overschrijven, in plaats daarvan wordt een nieuwe rij ingevoegd en de oude rij is verborgen. Nadat de transactie is doorgevoerd, kan het vacuümproces de verborgen rij verwijderen.

Planner

De taak van de planner is om de queryregels te nemen en te begrijpen welke van de verschillende manieren waarop de query kan worden uitgevoerd, het snelst is.

De planner maakt een planstructuur, met knooppunten die fysieke bewerkingen op de gegevens vertegenwoordigen.

PostgreSQL maakt gebruik van een optimalisatiefunctie voor kostenquery's om het optimale plan voor een query te vinden. De planner evalueert verschillende uitvoeringsplannen en schat hoeveel van de vereiste resources er nodig zijn, zoals CPU-cycli, I/O-bewerkingen, enzovoort. Deze schatting wordt vervolgens geconverteerd naar eenheden, ook wel de plankostengenoemd. Het plan met de laagste kosten wordt geselecteerd.

Naarmate het aantal joins echter toeneemt, neemt het aantal mogelijke plannen exponentieel toe. Het evalueren van elk mogelijk plan wordt onmogelijk, zelfs voor relatief eenvoudige query's. Heuristiek en algoritmen worden gebruikt om het aantal mogelijke plannen te beperken. Het resultaat is dat het geselecteerde plan mogelijk niet het optimale plan is. Het is echter bijna optimaal en binnen een redelijke tijd geselecteerd.

De kosten zijn de beste schatting van de planner. Het doel van de kostenraming is om verschillende uitvoeringsplannen voor de dezelfde query in dezelfde voorwaarden te vergelijken. De planner maakt gebruik van statistieken die in tabellen en rijen worden verzameld om kostenramingen voor query's te maken. Voor een nauwkeurige schatting van de kosten moeten statistieken up-to-date zijn.

Actuele statistieken

Het planneronderdeel van de queryoptimalisatie maakt gebruik van statistieken over tabellen en rijen om nauwkeurige kostenramingen te maken.

ANALYZE verzamelt statistieken over databasetabellen en slaat de resultaten op in de pg_statistic systeemcatalogus. U moet ANALYSEREN uitvoeren als:

  • U hebt autovacuum uitgeschakeld (waarbij tabellen normaal gesproken automatisch worden geanalyseerd)
  • U heeft autovacuumuitgeschakeld en heeft ANALYZE nog niet onlangs uitgevoerd.
  • Ofwel een van de vorige opties, en er zijn veel INSERT-, UPDATE- of DELETE-instructies.

Kostenramingen zijn afhankelijk van up-to-datumstatistieken en als statistieken verouderd zijn en een inefficiënt plan kan worden gekozen. Wanneer er geen parameter wordt doorgegeven aan ANALYZE, wordt elke tabel in de database onderzocht.

De syntaxis voor ANALYZE is:

ANALYZE [ VERBOSE ] [ ***table*** [ ( ***column*** [, ...] ) ] ]

Uitgebreid geeft voortgangsberichten weer om weer te geven welke tabel wordt geanalyseerd, samen met enkele statistieken.

Plan VACUUM en ANALYZE om dagelijks uit te voeren tijdens een periode van laag gebruik. ANALYZE kan parallel worden uitgevoerd met andere activiteiten, omdat hiervoor alleen een leesvergrendeling op de doeltabel is vereist.

Executeur

Deze fase neemt het plan dat door de planner is gemaakt en verwerkt het recursief om de vereiste verzameling rijen te extraheren. Telkens wanneer een plannode wordt aangeroepen, moet de uitvoerder een rij leveren of terugrapporteren dat het is voltooid.

De uitvoerder evalueert alle vier de SQL-querytypen:

  • SELECTEREN
  • INVOEGEN
  • UPDATE
  • VERWIJDEREN

Voor SELECT-retourneert de uitvoerder elke rij terug naar de client als resultaatset.

Voor INSERT-wordt elke geretourneerde rij in de opgegeven tabel ingevoegd. Deze taak wordt uitgevoerd in een speciaal plannode op toplevel met de naam ModifyTable.

Voor UPDATE-bevat elke berekende rij alle bijgewerkte kolomwaarden, plus de rij-id van de doelrij. De gegevens worden verzonden naar een ModifyTable-knooppunt, waarmee een bijgewerkte rij wordt gemaakt en de oude rij wordt gemarkeerd als verwijderd.

Voor DELETEis de enige kolom die door het plan wordt geretourneerd, de rij-ID. Het knooppunt ModifyTable gebruikt de rij-id om de rij te markeren als verwijderd.