Documentation PostgreSQL 9.0.23 > Internes > Présentation des mécanismes internes de PostgreSQL > Exécuteur | |
Planificateur/Optimiseur | Catalogues système |
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 quatre types de requêtes de base en SQL : SELECT, INSERT, UPDATE et DELETE. 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. Pour INSERT, chaque ligne renvoyée est insérée dans la table cible indiquée par INSERT. Cela se fait dans un nœud spécial haut niveau du plan appelé ModifyTable. (Une simple commande INSERT ... VALUES crée un arbre plan trivial constitué d'un seul nœud, Result, calculant une seule ligne de résultat, et ModifyTable au-dessus pour réaliser l'insertion. Mais INSERT ... SELECT peut demander la pleine puissance du mécanisme de l'exécuteur.) Pour UPDATE, le planificateur s'arrange pour que chaque ligne calculée inclue toutes les valeurs mises à jour des colonnes, plus le TID (tuple ID ou l'identifiant de la ligne) de la ligne de la cible originale ; cette donnée est envoyée dans un nœud ModifyTable, qui utilise l'information pour créer une nouvelle ligne mise à jour et marquer l'ancienne ligne comme supprimée. Pour DELETE, la seule colonne renvoyée par le plan est le TID, et ModifyTable node utilise simplement le TID pour visiter chaque ligne cible et la marquer comme supprimée.