Identifier les composants de traitement des requêtes
Il existe quatre étapes distinctes pour exécuter la requête. Dans l’ordre d’exécution, ces étapes sont les suivantes :
- Analyse
- Transformation (réécriture)
- Planification
- Exécution
Analyseur
L’analyseur est responsable de la vérification de la chaîne de requête pour la syntaxe valide. L’analyseur comporte deux parties principales :
- gram.y qui est constitué d’un ensemble de règles de grammaire et d’actions correspondantes.
- scan.1lexer, qui reconnaît les identificateurs et les mots clés SQL. Chaque mot clé ou identificateur déclenche la création et la remise d’un jeton à l’analyseur.
L’analyseur génère une arborescence de requêtes, qui sépare la requête en parties identifiables pour comprendre quelles tables sont impliquées, quels filtres ont été appliqués, etc. Les parties d’une arborescence de requêtes sont les suivantes :
- Type de commande : SELECT, INSERT, UPDATE ou DELETE.
- Entrée de table de plage (RTE) : liste de relations, tables,
ie
sous-requêtes, résultats de jointures, etc. Dans une instruction SELECT, ces éléments apparaissent après le mot clé FROM. - Relation de résultat : relation de résultat pour les commandes INSERT, UPDATE et DELETE, est la table ou la vue où les modifications doivent prendre effet.
- Liste cible : résultats de la requête, identifiés entre les mots clés SELECT et FROM. Les commandes DELETE ne produisent pas de résultat. Par conséquent, le planificateur ajoute une entrée spéciale pour permettre à l’exécuteur de trouver la ligne à supprimer. Les commandes INSERT identifient les nouvelles lignes qui doivent entrer dans la relation de résultat. Pour les commandes UPDATE, la liste cible décrit les nouvelles lignes qui doivent remplacer les anciennes.
- Qualification : valeur booléenne qui spécifie si l’opération de la ligne de résultat finale doit être exécutée ou non. Il correspond à la clause WHERE d’une instruction SQL.
- Arborescence de jointure : cette arborescence peut être une liste des éléments FROM. Les jointures peuvent être effectuées dans n’importe quel ordre ou dans un ordre spécifique, comme les jointures externes.
- Autres : éléments qui ne sont pas pertinents à ce stade, tels que la clause ORDER BY.
Module de réécriture
La sortie de l’analyseur est passée au processus de transformation ou de réécriture , sauf si une erreur est trouvée dans ce cas, un message d’erreur est retourné.
Le module de réécriture réécrit le texte de la requête en y appliquant des règles. Le réécriteur prend en compte les règles, puis transmet la requête modifiée au planificateur de requêtes. La sécurité au niveau des lignes est implémentée lors de cette phase.
Par exemple, les règles sur SELECT sont toujours appliquées comme dernière étape, notamment pour les requêtes INSERT, UPDATE et DELETE. Les règles signifient également que les requêtes UPDATE ne remplacent pas les lignes existantes, qu’une nouvelle ligne est insérée et que l’ancienne ligne est masquée. Une fois la transaction validée, le processus de vidage peut supprimer la ligne masquée.
Planificateur
Le travail du planificateur consiste à prendre les règles de requête et à comprendre quelle est la manière la plus rapide parmi les différentes façons dont la requête peut être exécutée.
Le planificateur crée une arborescence de plan, avec des nœuds représentant des opérations physiques sur les données.
PostgreSQL utilise un optimiseur de requête basé sur les coûts pour trouver le plan optimal d’une requête. Le planificateur évalue différents plans d’exécution et estime la quantité de ressources requises nécessaires, telles que les cycles d’UC, les opérations d’E/S, etc. Cette estimation est ensuite convertie en unités, appelée coût du plan. Le plan avec le coût le plus bas est sélectionné.
Toutefois, à mesure que le nombre de jointures augmente, le nombre de plans possibles augmente de façon exponentielle. L’évaluation de chaque plan possible devient impossible même pour les requêtes relativement simples. Les heuristiques et les algorithmes sont utilisés pour limiter le nombre de plans possibles. Le résultat est que le plan sélectionné peut ne pas être le plan optimal. Il est cependant quasi optimal et sélectionné dans un délai raisonnable.
Le coût est la meilleure estimation du planificateur. L’objectif de l’estimation des coûts est de comparer différents plans d’exécution pour la même requête dans les mêmes conditions. Le planificateur utilise des statistiques collectées sur les tables et les lignes pour produire des estimations de coût pour les requêtes. Pour que les estimations de coût soient précises, les statistiques doivent être à jour.
Statistiques à jour
Le composant planificateur de l’optimiseur de requête utilise des statistiques sur les tables et les lignes pour produire des estimations de coût précises.
ANALYZE collecte des statistiques sur les tables de base de données et stocke les résultats dans le catalogue système pg_statistic . Vous devez exécuter ANALYZE, si :
- Vous avez désactivé le nettoyage automatique (qui analyse normalement les tables automatiquement)
- Vous avez désactivé le nettoyage automatique et n’avez pas exécuté ANALYZE récemment
- Soit l'une des instructions précédentes, et il existe de nombreuses instructions INSERT, UPDATE ou DELETE.
Les estimations de coûts s'appuient sur les statistiques up-toactuelles, et si les statistiques sont obsolètes, un plan inefficace pourrait être choisi. Lorsqu’aucun paramètre n’est passé à ANALYZE, chaque table de la base de données est examinée.
La syntaxe de ANALYZE est la suivante :
ANALYZE [ VERBOSE ] [ ***table*** [ ( ***column*** [, ...] ) ] ]
VERBOSE affiche les messages de progression pour afficher la table à analyser, ainsi que certaines statistiques.
Planifiez l’exécution quotidienne de VACUUM et ANALYZE pendant une période de faible utilisation. ANALYZE peut s’exécuter en parallèle avec d’autres activités, car il ne nécessite qu’un verrou de lecture sur la table cible.
Exécuteur
Cette phase prend le plan créé par le planificateur et le traite de manière récursive pour extraire l’ensemble de lignes requis. Chaque fois qu’un nœud de plan est appelé, l’exécuteur doit remettre une ligne ou afficher un message indiquant qu’il a terminé.
L’exécuteur évalue les quatre types de requêtes SQL :
- Sélectionner
- INSERTION
- MISE À JOUR
- Supprimer
Pour SELECT, l’exécuteur retourne chaque ligne au client en tant que jeu de résultats.
Pour INSERT, chaque ligne retournée est insérée dans la table spécifiée. Cette tâche est effectuée dans un nœud spécial de plan de niveau supérieur appelé ModifyTable.
Pour UPDATE, chaque ligne calculée inclut toutes les valeurs de colonne mises à jour, ainsi que l’ID de ligne de la ligne cible. Les données sont envoyées à un nœud ModifyTable, qui crée une ligne mise à jour et marque l’ancienne ligne comme supprimée.
Pour DELETE, la seule colonne retournée par le plan est l’ID de ligne. Le nœud ModifyTable utilise l’ID de ligne pour marquer la ligne comme supprimée.