Nach dem Planner wirft PostgreSQL den sogenannten Executor an. Der Executor ist der Teil der Datenbank, der die eigentliche Arbeit mit den Daten übernimmt und einen Plan schließlich ausführt. Um einen Execution Plan sinnvoll ausführen zu können, benötigt der Executor einige Inputparameter. Der folgende Ausschnitt aus pquery.c zeigt, wie PostgreSQL prinzipiell vorgeht:
/*
* Must always set snapshot for plannable queries. Note we assume
* that caller will take care of restoring ActiveSnapshot on
* exit/error.
*/
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
/*
* Create the QueryDesc object
*/
queryDesc = CreateQueryDesc(parsetree, plan, ActiveSnapshot,
InvalidSnapshot, dest, params, false);
/*
* Set up to collect AFTER triggers
*/
AfterTriggerBeginQuery();
/*
* Call ExecStart to prepare the plan for execution
*/
ExecutorStart(queryDesc, false);
Von besonderer Bedeutung ist an dieser Stelle die Variable ActiveSnapshot: Ein Snapshot wird in PostgreSQL verwendet, um die Sichtbarkeit von Datensätzen zu beschreiben. Innerhalb eines Snapshots sind nur die für eine Transaktion relevanten Datensätze sichtbar - Datensätze, die eine andere Transaktion bereits gelöscht hat, werden von der aktuellen Transaktion also nicht berücksichtigt. Durch entsprechende Sichtbarkeitsregeln wird auch festgelegt, welche obsoleten Datenblöcke beispielsweise auch bereits zur Reallokation freigegeben sind.
Der Executor selbst wird mit einem sogenannten Query Descriptor gefüttert, der nahezu alle Informationen enthält, die der Executor zum Ausführen der Query benötigt. Neben dem aktuellen Parse Tree findet sich im Query Descriptor auch der auszuführende Plan. In unserem Listing sehen Sie auch eine Variable namens 'dest'. In unserem Fall gibt 'dest' an, wohin das Ergebnis geschrieben werden soll. Als Ziel kommen beispielsweise ein Client Interface oder dergleichen in Frage.
Oft kann es vorkommen, dass ein Execution Plan einen Funktionsaufruf enthält. In solchen Fällen hat der Executor die Möglichkeit, SQL-Statements, die von Funktionen aufgerufen werden, wieder an den Parser zu übergeben - der Weg einer Query durch die Datenbank ist also nicht unbedingt eine Einbahnstraße.