Lire les plans Aurora SQL EXPLAIN - Amazon Aurora DSQL

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Lire les plans Aurora SQL EXPLAIN

Comprendre comment lire les plans EXPLAIN est essentiel pour optimiser les performances des requêtes. Dans cette section, nous allons passer en revue des exemples concrets de plans de requêtes SQL Aurora, montrer le comportement des différents types de scan, expliquer où les filtres sont appliqués et mettre en évidence les opportunités d'optimisation.

Exemple de scan complet

Aurora DSQL propose à la fois des scans séquentiels, qui sont fonctionnellement identiques à PostgreSQL, ainsi que des scans complets. La seule différence entre les deux est que les scans complets peuvent utiliser un filtrage supplémentaire sur le stockage. Pour cette raison, il est presque toujours sélectionné au-dessus des scans séquentiels. En raison de la similitude, nous ne couvrirons que des exemples des scans complets les plus intéressants.

Les scans complets seront principalement utilisés sur des tables sans clé primaire. Étant donné que les clés primaires Aurora DSQL sont par défaut des index de couverture complets, Aurora DSQL utilisera très probablement des scans d'index uniquement sur la clé primaire dans de nombreuses situations où PostgreSQL utiliserait un scan séquentiel. Comme c'est le cas pour la plupart des autres bases de données, une table dépourvue d'index risque d'être mal dimensionnée.

EXPLAIN SELECT account_id FROM transaction WHERE transaction_date > '2025-01-01' AND description LIKE '%external%';
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Full Scan (btree-table) on transaction  (cost=125100.05..177933.38 rows=33333 width=16)
   Filter: (description ~~ '%external%'::text)
   -> Storage Scan on transaction (cost=12510.05..17793.38 rows=66666 width=16)
        Projections: account_id, description
        Filters: (transaction_date > '2025-01-01 00:00:00'::timestamp without time zone)
        -> B-Tree Scan on transaction (cost=12510.05..17793.38 rows=100000 width=30)

Ce plan montre deux filtres appliqués à différentes étapes. La transaction_date > '2025-01-01' condition est appliquée au niveau de la couche de stockage, ce qui réduit la quantité de données renvoyées. La description LIKE '%external%' condition est appliquée ultérieurement dans le processeur de requêtes, une fois les données transférées, ce qui le rend moins efficace. L'introduction de filtres plus sélectifs dans les couches de stockage ou d'index améliore généralement les performances.

Exemple de scan avec index uniquement

Les scans d'index uniquement sont les types de scan les plus optimaux dans Aurora DSQL, car ils permettent de réduire le nombre d'allers-retours vers la couche de stockage et sont ceux qui peuvent effectuer le plus de filtrage. Mais ce n'est pas parce que vous voyez Index Only Scan que vous avez le meilleur plan. En raison des différents niveaux de filtrage qui peuvent se produire, il est essentiel de rester attentif aux différents endroits où le filtrage peut se produire.

EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending';
                                  QUERY PLAN
-------------------------------------------------------------------------------
 Index Only Scan using idx1 on account  (cost=725.05..1025.08 rows=8 width=18)
   Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   Filter: (balance > '100'::numeric)
   -> Storage Scan on idx1 (cost=12510.05..17793.38 rows=9 width=16)
        Projections: balance
        Filters: ((status)::text = 'pending'::text)
        -> B-Tree Scan on idx1 (cost=12510.05..17793.38 rows=10 width=30)
            Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)

Dans ce plan, la condition de l'index customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' () est d'abord évaluée lors de l'analyse de l'index, qui est l'étape la plus efficace car elle limite la quantité de données lues depuis le stockage. Le filtre de stockage est appliqué après la lecture des donnéesstatus = 'pending', mais avant leur envoi à la couche de calcul, ce qui réduit la quantité de données transférées. Enfin, le filtre du processeur de requêtes s'exécute en dernier, une fois les données déplacées, ce qui le rend le moins efficace. balance > 100 Parmi celles-ci, la condition d'index fournit les meilleures performances car elle contrôle directement la quantité de données numérisées.

Exemple de scan d'index

Les scans d'index sont similaires aux scans d'index uniquement, sauf qu'ils comportent l'étape supplémentaire d'appel à la table de base. Comme Aurora DSQL peut spécifier des filtres de stockage, il est en mesure de le faire à la fois lors de l'appel d'index et lors de l'appel de recherche.

Pour que cela soit clair, Aurora DSQL présente le plan sous la forme de deux nœuds. De cette façon, vous pouvez clairement voir dans quelle mesure l'ajout d'une colonne d'inclusion sera utile en termes de lignes renvoyées par le stockage.

EXPLAIN SELECT balance FROM account WHERE customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb' AND balance > 100 AND status = 'pending' AND created_at > '2025-01-01';
                                                QUERY PLAN
----------------------------------------------------------------------------------------------------------
 Index Scan using idx1 on account  (cost=728.18..1132.20 rows=3 width=18)
   Filter: (balance > '100'::numeric)
   Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   -> Storage Scan on idx1 (cost=12510.05..17793.38 rows=8 width=16)
        Projections: balance
        Filters: ((status)::text = 'pending'::text)
        -> B-Tree Scan on account (cost=12510.05..17793.38 rows=10 width=30)
            Index Cond: (customer_id = '4b18a761-5870-4d7c-95ce-0a48eca3fceb'::uuid)
   -> Storage Lookup on account (cost=12510.05..17793.38 rows=4 width=16)
        Filters: (created_at > '2025-01-01 00:00:00'::timestamp without time zone)
        -> B-Tree Lookup on transaction (cost=12510.05..17793.38 rows=8 width=30)

Ce plan montre comment le filtrage s'effectue en plusieurs étapes :

  • La condition d'index sur les customer_id filtres permet de filtrer les données à un stade précoce.

  • Le filtre de stockage permet de status restreindre davantage les résultats avant qu'ils ne soient envoyés au calcul.

  • Le filtre du processeur de requêtes activé balance est appliqué ultérieurement, après le transfert.

  • Le filtre de recherche activé created_at est évalué lors de la récupération de colonnes supplémentaires dans la table de base.

L'ajout de colonnes fréquemment utilisées en tant que INCLUDE champs permet souvent d'éliminer cette recherche et d'améliorer les performances.

Bonnes pratiques

  • Alignez les filtres sur les colonnes indexées pour accélérer le filtrage.

  • Utilisez les colonnes INCLUDE pour autoriser les scans d'index uniquement et éviter les recherches.

  • Tenez les statistiques à jour pour garantir l'exactitude des estimations de coûts et de lignes.

  • Évitez les requêtes non indexées sur de grandes tables afin d'éviter des scans complets coûteux.