PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17.6 » Référence » Commandes SQL » EXPLAIN

EXPLAIN

EXPLAIN — Afficher le plan d'exĂ©cution d'une instruction

Synopsis

EXPLAIN [ ( option [, ...] ) ] instruction

oĂč option est :

    ANALYZE [ boolean ]
    VERBOSE [ boolean ]
    COSTS [ boolean ]
    SETTINGS [ boolean ]
    GENERIC_PLAN [ boolean ]
    BUFFERS [ boolean ]
    SERIALIZE [ { NONE | TEXT | BINARY } ]
    WAL [ boolean ]
    TIMING [ boolean ]
    SUMMARY [ boolean ]
    MEMORY [ boolean ]
    FORMAT { TEXT | XML | JSON | YAML }

  

Description

Cette commande affiche le plan d'exĂ©cution que l'optimiseur de PostgreSQL engendre pour l'instruction fournie. Le plan d'exĂ©cution dĂ©crit le parcours de la (des) table(s) utilisĂ©e(s) dans la requĂȘte -- parcours sĂ©quentiel, parcours d'index, etc. -- . Si plusieurs tables sont rĂ©fĂ©rencĂ©es, il prĂ©sente Ă©galement les algorithmes de jointures utilisĂ©s pour rassembler les lignes issues des diffĂ©rentes tables.

La partie la plus importante de l'affichage concerne l'affichage des coĂ»ts estimĂ©s d'exĂ©cution. Ils reprĂ©sentent l'estimation faite par le planificateur des temps d'exĂ©cution de la requĂȘte (mesurĂ© en une unitĂ© de coĂ»t arbitraire bien que conventionnellement ce sont des lectures de page disque). Deux nombres sont affichĂ©s : le coĂ»t de dĂ©marrage, Ă©coulĂ© avant que la premiĂšre ligne soit renvoyĂ©e, et le coĂ»t d'exĂ©cution total, nĂ©cessaire au renvoi de toutes les lignes. Pour la plupart des requĂȘtes, le coĂ»t qui importe est celui d'exĂ©cution totale. Mais dans certains cas, tel que pour une sous-requĂȘte dans la clause EXISTS, le planificateur choisira le coĂ»t de dĂ©marrage le plus court, et non celui d'exĂ©cution totale (car, de toute façon, l'exĂ©cuteur s'arrĂȘte aprĂšs la rĂ©cupĂ©ration d'une ligne). De mĂȘme, lors de la limitation des rĂ©sultats Ă  retourner par une clause LIMIT, la planificateur effectue une interpolation entre les deux coĂ»ts limites pour choisir le plan rĂ©ellement le moins coĂ»teux.

L'option ANALYZE impose l'exĂ©cution de la requĂȘte en plus de sa planification. De ce fait, les statistiques d'exĂ©cution rĂ©elle sont ajoutĂ©es Ă  l'affichage, en incluant le temps total Ă©coulĂ© Ă  chaque nƓud du plan (en millisecondes) et le nombre total de lignes renvoyĂ©es. C'est utile pour vĂ©rifier la vĂ©racitĂ© des informations fournies par le planificateur.

Important

Il ne faut pas oublier que l'instruction est rĂ©ellement exĂ©cutĂ©e avec l'option ANALYZE. Bien qu'EXPLAIN inhibe l'affichage des retours d'une commande SELECT, les autres effets de l'instruction sont prĂ©sents. Si EXPLAIN ANALYZE doit ĂȘtre utilisĂ© sur une instruction INSERT, UPDATE, DELETE, MERGE, CREATE TABLE AS ou EXECUTE sans que la commande n'affecte les donnĂ©es, l'approche suivante peut ĂȘtre envisagĂ©e :

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;
    

ParamĂštres

ANALYZE

Exécute la commande et affiche les temps d'exécution réels et d'autres statistiques. Ce paramÚtre est par défaut à FALSE.

VERBOSE

Affiche des informations supplĂ©mentaires sur le plan. Cela inclut la liste des colonnes en sortie pour chaque nƓud du plan, les noms des tables et fonctions avec le nom du schĂ©ma, les labels des variables dans les expressions avec des alias de tables et le nom de chaque trigger pour lesquels les statistiques sont affichĂ©es. L'identifiant de requĂȘte sera aussi affichĂ© si une requĂȘte a Ă©tĂ© Ă©valuĂ©e, voir compute_query_id pour plus de dĂ©tails. Ce paramĂštre est par dĂ©faut Ă  FALSE.

COSTS

Inclut des informations sur le coĂ»t estimĂ© au dĂ©marrage et au total de chaque nƓud du plan, ainsi que le nombre estimĂ© de lignes et la largeur estimĂ©e de chaque ligne. Ce paramĂštre est par dĂ©faut Ă  TRUE.

GENERIC_PLAN

Autorise la requĂȘte Ă  contenir des caractĂšres joker de placement comme $1, et gĂ©nĂšre un plan gĂ©nĂ©rique qui ne dĂ©pend pas de ces paramĂštres. Voir PREPARE pour les dĂ©tails sur les plans gĂ©nĂ©riques et les types de requĂȘtes qui acceptent des paramĂštres. Ce paramĂštre ne peut pas ĂȘtre utilisĂ© en mĂȘme temps que ANALYZE. Il est Ă  FALSE par dĂ©faut.

BUFFERS

Inclut des informations sur l'utilisation des tampons. SpĂ©cifiquement, inclut le nombre de blocs partagĂ©s lus dans la cache, lus en dehors du cache, modifiĂ©s et Ă©crits, le nombre de blocs locaux lus dans le cache, lus en dehors du cache, modifiĂ©s, et Ă©crits, et le nombre de blocs temporaires lus et Ă©crits, et le temps passĂ© Ă  lire et Ă©crire des blocs dans les fichiers de donnĂ©es, dans les blocs locaux et dans les fichiers temporaires (en millisecondes) si le paramĂštre track_io_timing est activĂ©. Le terme hit signifie que la lecture a Ă©tĂ© Ă©vitĂ©e car le bloc se trouvait dĂ©jĂ  dans le cache. Les blocs partagĂ©s contiennent les donnĂ©es de tables et index standards ; les blocs locaux contiennent les tables et index temporaires ; les blocs temporaires contiennent les donnĂ©es de travail Ă  court terme, comme les tris, les hachages, les nƓuds Materialize, et des cas similaires. Le nombre de blocs modifiĂ©s (dirtied) indique le nombre de blocs prĂ©cĂ©demment propres qui ont Ă©tĂ© modifiĂ©s par cette requĂȘte ; le nombre de blocs Ă©crits (written) indique le nombre de blocs dĂ©jĂ  modifiĂ©s qui a Ă©tĂ© enlevĂ© du cache pour ĂȘtre Ă©crit sur disque lors de l'exĂ©cution de cette requĂȘte. Le nombre de blocs affichĂ©s pour un nƓud de niveau supĂ©rieur inclut ceux utilisĂ©s par tous ses enfants. Dans le format texte, seules les valeurs diffĂ©rentes de zĂ©ro sont affichĂ©es. La valeur par dĂ©faut de ce paramĂštre est FALSE.

SETTINGS

Inclut des informations sur les paramĂštres de configuration. Plus prĂ©cisĂ©ment, inclut les options affectant l'optimisation des requĂȘtes et qui ont des valeurs diffĂ©rentes de leur valeur par dĂ©faut. Sa valeur par dĂ©faut est FALSE.

SERIALIZE

Inclut des informations sur le coĂ»t de sĂ©rialisation des donnĂ©es en sortie de la requĂȘte, autrement dit la conversion en format texte ou binaire Ă  envoyer au client. Ceci peut ĂȘtre une part significative du temps nĂ©cessaire pour l'exĂ©cution rĂ©guliĂšre d'une requĂȘte, si les fonctions en sortie sont coĂ»teuses ou si des valeurs duTOAST doivent ĂȘtre rĂ©cupĂ©rĂ©es. Le comportement par dĂ©faut de EXPLAIN, SERIALIZE NONE, ne rĂ©alise pas ces conversions. Si SERIALIZE TEXT ou SERIALIZE BINARY est indiquĂ©, les conversions appropriĂ©es sont rĂ©alisĂ©es et le temps passĂ© Ă  le faire est mesurĂ© (sauf si TIMING OFF est indiquĂ©). Si l'option BUFFERS est aussi indiquĂ©, alors tout accĂšs au cache impliquĂ© dans les conversions est aussi comptĂ©. Cependant, en aucun cas, EXPLAIN n'enverra les donnĂ©es rĂ©sultantes au client ; de ce fait, les coĂ»ts de transmission sur le rĂ©seau ne peuvent pas ĂȘtre investiguĂ©s de cette façon. La sĂ©rialisation peut seulement ĂȘtre activĂ©e quand ANALYZE est aussi activĂ©. Si SERIALIZE est Ă©crit sans argument, TEXT est la valeur utilisĂ©e.

WAL

Inclut des informations sur les gĂ©nĂ©ration des enregistrements dans les WAL. SpĂ©cifiquement, inclut le nombre d'enregistrements, le nombre d'images complĂšte de bloc (FPI), et la quantitĂ© d'octets gĂ©nĂ©rĂ©s dans les WAL. Dans le format texte, seules les valeurs diffĂ©rentes de zĂ©ro seront affichĂ©es. Ce paramĂštre peut seulement aussi ĂȘtre utilisĂ© quand ANALYZE est aussi activĂ©. Il vaut par dĂ©faut FALSE.

TIMING

Inclut le temps rĂ©el de dĂ©marrage et le temps rĂ©el passĂ© dans le nƓud en sortie. La surcharge de la lecture rĂ©pĂ©tĂ©e de l'horloge systĂšme peut ralentir la requĂȘte de façon significative sur certains systĂšmes, et donc il est utile de pouvoir configurer ce paramĂštre Ă  FALSE quand seuls le dĂ©compte rĂ©el des lignes est nĂ©cessaire. La durĂ©e d'exĂ©cution complĂšte de la commande est toujours mesurĂ©e, mĂȘme si le chronomĂ©trage des nƓuds est dĂ©sactivĂ© avec cette option. Ce paramĂštre peut seulement ĂȘtre utilisĂ© quand l'option ANALYZE est aussi activĂ©e. La valeur par dĂ©faut est TRUE.

SUMMARY

Inclut des informations rĂ©sumĂ©es (par exemple : information de temps total) aprĂšs le plan de la requĂȘte. Les informations rĂ©sumĂ©es sont inclues par dĂ©faut quand ANALYZE est utilisĂ© mais sinon ne sont pas inclues par dĂ©faut, mais peuvent ĂȘtre activĂ©es avec cette option. Le temps de planification dans EXPLAIN EXECUTE inclut le temps nĂ©cessaire pour rĂ©cupĂ©rer le plan du cache ainsi que le temps nĂ©cessaire pour le replanifier, si nĂ©cessaire.

MEMORY

Inclut des informations sur la consommation mĂ©moire par la phase d'optimisation de la requĂȘte. Plus spĂ©cifiquement, inclut la quantitĂ© prĂ©cise de stockage utilisĂ© par l'optimiseur pour les structures en mĂ©moire, ainsi qu'un total de mĂ©moire. Ce paramĂštre vaut par dĂ©faut FALSE.

FORMAT

Indique le format de sortie. Il peut valoir TEXT, XML, JSON ou YAML. Toutes les sorties contiennent les mĂȘmes informations, mais les programmes pourront plus facilement traiter les sorties autres que TEXT. Ce paramĂštre est par dĂ©faut Ă  TEXT.

boolean

SpĂ©cifie si l'option sĂ©lectionnĂ©e doit ĂȘtre activĂ©e ou dĂ©sactivĂ©e. Vous pouvez Ă©crire TRUE, ON ou 1 pour activer l'option, et FALSE, OFF ou 0 pour la dĂ©sactiver. La valeur de type boolean peut aussi ĂȘtre omise, auquel cas la valeur sera TRUE.

instruction

Toute instruction SELECT, INSERT, UPDATE, DELETE, MERGE, VALUES, EXECUTE, DECLARE, CREATE TABLE AS ou CREATE MATERIALIZED VIEW AS dont le plan d'exécution est souhaité.

Sorties

La sortie de la commande est une description textuelle du plan sĂ©lectionnĂ© pour la requĂȘte, annotĂ©e en option des statistiques d'exĂ©cution. Section 14.1 dĂ©crit les informations fournies.

Notes

Pour permettre au planificateur de requĂȘtes de PostgreSQL de prendre des dĂ©cisions en Ă©tant raisonnablement informĂ© pour l'optimisation des requĂȘtes, les donnĂ©es du catalogue pg_statistic doivent ĂȘtre Ă  jour pour toutes les tables utilisĂ©es dans la requĂȘte. Habituellement, le dĂ©mon autovacuum s'en chargera automatiquement. Mais si une table a eu rĂ©cemment des changements importants dans son contenu, vous pourriez avoir besoin de lancer un ANALYZE manuel plutĂŽt que d'attendre que l'autovacuum s'occupe des modifications.

Pour mesurer le coĂ»t d'exĂ©cution de chaque nƓud dans le plan d'exĂ©cution, l'implĂ©mentation actuelle de la commande EXPLAIN ANALYZE ajoute une surcharge de profilage Ă  l'exĂ©cution de la requĂȘte. En rĂ©sultat, exĂ©cuter EXPLAIN ANALYZE sur une requĂȘte peut parfois prendre un temps significativement plus long que l'exĂ©cution de la requĂȘte. La durĂ©e supplĂ©mentaire dĂ©pend de la nature de la requĂȘte ainsi que de la plateforme utilisĂ©e. Le pire des cas survient pour les nƓuds du plan nĂ©cessitant en eux-mĂȘme peu de durĂ©e d'exĂ©cution par exĂ©cution et sur les machines disposant d'appels systĂšmes relativement lents pour obtenir l'heure du jour.

Exemples

Afficher le plan d'une requĂȘte simple sur une table d'une seule colonne de type integer et 10000 lignes :

EXPLAIN SELECT * FROM foo;

                       QUERY PLAN
---------------------------------------------------------
 Seq Scan on foo  (cost=0.00..155.00 rows=10000 width=4)
(1 row)
   

Voici le mĂȘme plan, mais formatĂ© avec JSON :

EXPLAIN (FORMAT JSON) SELECT * FROM foo;
           QUERY PLAN
--------------------------------
 [                             +
   {                           +
     "Plan": {                 +
       "Node Type": "Seq Scan",+
       "Relation Name": "foo", +
       "Alias": "foo",         +
       "Startup Cost": 0.00,   +
       "Total Cost": 155.00,   +
       "Plan Rows": 10000,     +
       "Plan Width": 4         +
     }                         +
   }                           +
 ]
(1 row)
   

S'il existe un index et que la requĂȘte contient une condition WHERE indexable, EXPLAIN peut afficher un plan diffĂ©rent :

EXPLAIN SELECT * FROM foo WHERE i = 4;

                         QUERY PLAN
--------------------------------------------------------------
 Index Scan using fi on foo  (cost=0.00..5.98 rows=1 width=4)
   Index Cond: (i = 4)
(2 rows)
   

Voici le mĂȘme plan, mais formatĂ© avec YAML :

EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4';
          QUERY PLAN
-------------------------------
 - Plan:                      +
     Node Type: "Index Scan"  +
     Scan Direction: "Forward"+
     Index Name: "fi"         +
     Relation Name: "foo"     +
     Alias: "foo"             +
     Startup Cost: 0.00       +
     Total Cost: 5.98         +
     Plan Rows: 1             +
     Plan Width: 4            +
     Index Cond: "(i = 4)"
(1 row)
   

L'obtention du format XML est laissé en exercice au lecteur.

Voici le mĂȘme plan avec les coĂ»ts supprimĂ©s :

EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;

        QUERY PLAN
----------------------------
 Index Scan using fi on foo
   Index Cond: (i = 4)
(2 rows)
   

Exemple de plan de requĂȘte pour une requĂȘte utilisant une fonction d'agrĂ©gat :

EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;

                             QUERY PLAN
---------------------------------------------------------------------
 Aggregate  (cost=23.93..23.93 rows=1 width=4)
   ->  Index Scan using fi on foo  (cost=0.00..23.92 rows=6 width=4)
         Index Cond: (i < 10)
(3 rows)
   

Exemple d'utilisation de EXPLAIN EXECUTE pour afficher le plan d'exĂ©cution d'une requĂȘte prĂ©parĂ©e :

PREPARE query(int, int) AS SELECT sum(bar) FROM test
    WHERE id > $1 AND id < $2
    GROUP BY foo;

EXPLAIN ANALYZE EXECUTE query(100, 200);

                                                       QUERY PLAN
-------------------------------------------------------------------------------------
 HashAggregate  (cost=10.77..10.87 rows=10 width=12) (actual time=0.043..0.044 rows=10 loops=1)
   Group Key: foo
   Batches: 1  Memory Usage: 24kB
   ->  Index Scan using test_pkey on test  (cost=0.29..10.27 rows=99 width=8) (actual time=0.009..0.025 rows=99 loops=1)
         Index Cond: ((id > 100) AND (id < 200))
 Planning Time: 0.244 ms
 Execution Time: 0.073 ms
(7 rows)
   

Il est Ă©vident que les nombres prĂ©sentĂ©s ici dĂ©pendent du contenu effectif des tables impliquĂ©es. De plus, les nombres, et la stratĂ©gie sĂ©lectionnĂ©e elle-mĂȘme, peuvent diffĂ©rer en fonction de la version de PostgreSQL du fait des amĂ©liorations apportĂ©es au planificateur. Il faut Ă©galement savoir que la commande ANALYZE calcule les statistiques des donnĂ©es Ă  partir d'extraits alĂ©atoires ; il est de ce fait possible que les coĂ»ts estimĂ©s soient modifiĂ©s aprĂšs l'exĂ©cution de cette commande, alors mĂȘme la distribution rĂ©elle des donnĂ©es dans la table n'a pas changĂ©.

Notez que l'exemple prĂ©cĂ©dent montrait un plan « personnalisĂ© Â» pour les valeurs spĂ©cifiques des paramĂštres donnĂ©es dans EXECUTE. Nous pourrions aussi souhaiter voir le plan gĂ©nĂ©rique pour une requĂȘte Ă  paramĂštre, ce qui peut se faire avec GENERIC_PLAN :

EXPLAIN (GENERIC_PLAN)
  SELECT sum(bar) FROM test
    WHERE id > $1 AND id < $2
    GROUP BY foo;

                                  QUERY PLAN
-------------------------------------------------------------------​------------
 HashAggregate  (cost=26.79..26.89 rows=10 width=12)
   Group Key: foo
   ->  Index Scan using test_pkey on test  (cost=0.29..24.29 rows=500 width=8)
         Index Cond: ((id > $1) AND (id < $2))
(4 rows)

Dans ce cas, l'analyseur dĂ©tecte correctement que $1 et $2 devraient avoir le mĂȘme type de donnĂ©es que id, donc la manque d'information sur le type de paramĂštre par PREPARE n'Ă©tait pas un problĂšme. Dans d'autres cas, il pourrait ĂȘtre nĂ©cessaire de spĂ©cifier explicitement les types pour les symboles des paramĂštres, ce qui peut se faire en les convertissant. Par exemple :

EXPLAIN (GENERIC_PLAN)
  SELECT sum(bar) FROM test
    WHERE id > $1::integer AND id < $2::integer
    GROUP BY foo;

Compatibilité

L'instruction EXPLAIN n'est pas définie dans le standard SQL.

La syntaxe suivante Ă©tait utilisĂ©e avant la version 9.0 de PostgreSQL et est toujours acceptĂ©e :

EXPLAIN [ ANALYZE ] [ VERBOSE ] requete

Notez que, dans cette syntaxe, les options doivent ĂȘtre indiquĂ©es dans l'ordre exact affichĂ©.

Voir aussi

ANALYZE