PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 15.6 » Internes » Présentation des mécanismes internes de PostgreSQL » Exécuteur

52.6. Exécuteur

L'exécuteur prend le plan créé par le planificateur/optimiseur et l'exécute récursivement pour extraire l'ensemble requis de lignes. Il s'agit principalement d'un mécanisme de pipeline en demande-envoi. Chaque fois qu'un nœud du plan est appelé, il doit apporter une ligne supplémentaire ou indiquer qu'il a fini d'envoyer des lignes.

Pour donner un exemple concret, on peut supposer que le nœud supérieur est un nœud MergeJoin. Avant de pouvoir faire une fusion, deux lignes doivent être récupérées (une pour chaque sous-plan). L'exécuteur s'appelle donc récursivement pour exécuter les sous-plans (en commençant par le sous-plan attaché à l'arbre gauche). Le nouveau nœud supérieur (le nœud supérieur du sous-plan gauche) est, par exemple, un nœud Sort (NdT : Tri) et un appel récursif est une nouvelle fois nécessaire pour obtenir une ligne en entrée. Le nœud fils de Sort pourrait être un nœud SeqScan, représentant la lecture réelle d'une table. L'exécution de ce nœud impose à l'exécuteur de récupérer une ligne à partir de la table et de la retourner au nœud appelant. Le nœud Sort appelle de façon répétée son fils pour obtenir toutes les lignes à trier. Quand l'entrée est épuisée (indiqué par le nœud fils renvoyant un NULL au lieu d'une ligne), le code de Sort est enfin capable de renvoyer sa première ligne en sortie, c'est-à-dire le premier suivant l'ordre de tri. Il conserve les lignes restantes en mémoire de façon à les renvoyer dans le bon ordre en réponse à des demandes ultérieures.

Le nœud MergeJoin demande de la même façon la première ligne à partir du sous-plan droit. Ensuite, il compare les deux lignes pour savoir si elles peuvent être jointes ; si c'est le cas, il renvoie la ligne de jointure à son appelant. Au prochain appel, ou immédiatement, s'il ne peut pas joindre la paire actuelle d'entrées, il avance sur la prochaine ligne d'une des deux tables (suivant le résultat de la comparaison), et vérifie à nouveau la correspondance. Éventuellement, un des sous-plans est épuisé et le nœud MergeJoin renvoie NULL pour indiquer qu'il n'y a plus de lignes jointes à former.

Les requêtes complexes peuvent nécessiter un grand nombre de niveaux de nœuds pour les plans, mais l'approche générale est la même : chaque nœud est exécuté et renvoie sa prochaine ligne en sortie à chaque fois qu'il est appelé. Chaque nœud est responsable aussi de l'application de toute expression de sélection ou de projection qui lui a été confiée par le planificateur.

Le mécanisme de l'exécuteur est utilisé pour évaluer les cinq types de requêtes de base en SQL : SELECT, INSERT, UPDATE, DELETE et MERGE. Pour SELECT, le code de l'exécuteur de plus haut niveau a uniquement besoin d'envoyer chaque ligne retournée par l'arbre plan de la requête vers le client. INSERT ... SELECT, UPDATE, DELETE et MERGE sont en réalité des SELECT sous un nœud de plan haut niveau appelé ModifyTable.

INSERT ... SELECT remplit les lignes de ModifyTable pour insertion. Pour UPDATE, l'optimiseur s'arrange pour que chaque ligne traitée inclut toutes les valeurs mises à jour des colonnes, plus le TID (tuple ID, ou identifiant de ligne) de la ligne cible originale ; cette donnée est envoyée au nœud ModifyTable, qui utilise l'information pour créer un nouveau nœud mis à jour et pour marquer l'ancienne ligne comme supprimée. Pour DELETE, la seule colonne qui est réellement renvoyée par le plan est le TID, et le nœud ModifyTable utilise simplement le TID pour visiter chaque ligne cible et la marquer supprimée. Pour MERGE, l'optimiseur joint les relations source et cible, et inclut toutes les valeurs de colonne requises par chaque clause WHEN, plus le TID de la ligne cible ; cette donnée est fournie au nœud ModifyTable qui utilise l'information pour trouver la clause WHEN à exécuter, puis insère, met à jour ou supprime la ligne cible, suivant le besoin exprimé.

Une simple commande INSERT ... VALUES crée un arbre de plan trivial consistant en un seul nœud Result, qui calcule seulement une ligne résultat, en l'envoyant à ModifyTable pour réaliser l'insertion.