Requete plan execution

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Type Script SQL*Plus de diagnostic
Objet Plan d'exécution (EXPLAIN PLAN)
Voir aussi Perf top sql by disk reads · Perf top sql by buffer gets

Requete plan execution capture et affiche le plan d'exécution d'une requête SQL via EXPLAIN PLAN et la table PLAN_TABLE, en le mettant en forme sous forme d'arbre indenté (requête hiérarchique CONNECT BY). Utile pour comprendre pourquoi une requête identifiée comme coûteuse (voir Perf top sql by buffer gets / Perf top sql by disk reads) est lente : full scan au lieu d'un accès par index, mauvais ordre de jointure, etc.

⚠️ Prérequis : la table PLAN_TABLE doit exister dans le schéma courant. Si ce n'est pas le cas, la créer au préalable avec le script fourni par Oracle :

@?/rdbms/admin/utlxplan.sql

(? représente $ORACLE_HOME dans un script SQL*Plus.)

Script

SET ECHO     OFF
SET PAGESIZE 1000
SET FEEDBACK OFF
SET LINESIZE 15000

COLUMN operation    FORMAT A45
COLUMN type_acces   FORMAT A20
COLUMN nom_objet    FORMAT A30
COLUMN ordre        FORMAT A8
COLUMN etat         FORMAT A20

-- Purge un éventuel plan précédent portant le même identifiant
DELETE FROM plan_table WHERE statement_id = 'X';

EXPLAIN PLAN
SET statement_id = 'X'
INTO plan_table
FOR
<requête à analyser>
;

SELECT
    LPAD(' ', 2 * (LEVEL - 1)) || operation                                          "OPERATION"
  , options                                                                          "TYPE_ACCES"
  , DECODE(TO_CHAR(id), '0', 'COST= ' || NVL(TO_CHAR(position), 'Indéfini'), object_name) "NOM_OBJET"
  , id || '-' || NVL(parent_id, 0) || '-' || NVL(position, 0)                        "ORDRE"
  , ' COUT=' || cost || ',' || 'CARD=' || cardinality                                "COUT_OP"
FROM
    plan_table
START WITH
    id = 0
    AND statement_id = 'X'
CONNECT BY PRIOR
    id = parent_id
    AND statement_id = 'X';

Remplacer <requête à analyser> par la requête SQL réelle (sans point-virgule interne), par exemple :

EXPLAIN PLAN
SET statement_id = 'X'
INTO plan_table
FOR
SELECT * FROM employes WHERE departement_id = 10
;

Alternative moderne

Depuis Oracle 9i, le package DBMS_XPLAN simplifie fortement cette manipulation (mise en forme automatique, pas besoin de gérer statement_id à la main) :

EXPLAIN PLAN FOR
SELECT * FROM employes WHERE departement_id = 10;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

Ou, pour afficher le plan réellement utilisé par une requête déjà exécutée (à partir du cache, avec les statistiques d'exécution réelles) :

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

Voir aussi