EXPLAIN PLAN
目的
EXPLAIN
PLAN
文を使用すると、指定したSQL文を実行するためにOracle Databaseが使用する実行計画を決定できます。この文によって、実行計画の各ステップを記述している行が、指定した表に挿入されます。SQLトレース機能の一部としてEXPLAIN
PLAN
文を発行することもできます。
この文によって、文を実行するコストも決まります。表にドメイン索引が定義されている場合、ユーザー定義のCPUおよびI/Oコストが挿入されます。
配布メディアのSQLスクリプトの中に、サンプル出力表PLAN_TABLE
の定義があります。使用する出力表は、列の名前およびデータ型がこのサンプル表と同じである必要があります。このスクリプトの一般的な名前は、UTLXPLAN.SQL
です。正確な名前および位置は、使用するオペレーティング・システムによって異なります。
キャッシュされたカーソルに関する情報は、次の動的パフォーマンス・ビューから得られます。
-
SQLカーソルが使用する作業領域の詳細は、
V$SQL_WORKAREA
を問い合せます。 -
キャッシュされたカーソルの実行計画の詳細は、
V$SQL_PLAN
を問い合せます。 -
キャッシュされたカーソルの各ステップでの実行統計または実行計画の操作(生成された行数、読み取られたブロック数など)は、
V$SQL_PLAN_STATISTICS
を問い合せます。 -
前述の3つのビューの処理結果を1つにまとめた情報を取得する場合は、
V$SQL_PLAN_STATISTICS_ALL
を問い合せます。 -
この文の実行が監視されている場合、キャッシュされたカーソルの実行計画の各ステップまたは各操作での実行統計は、
V$SQL_PLAN_MONITOR
に表示されます。MONITOR
ヒントを使用すると、監視を強制的に適用できます。
関連項目:
-
EXPLAIN
PLAN
の出力、SQLトレース機能の使用方法、および実行計画の生成と解析方法については、『Oracle Database SQLチューニング・ガイド』を参照してください。 -
動的パフォーマンス・ビューの詳細は、『Oracle Databaseリファレンス』を参照してください。
前提条件
EXPLAIN
PLAN
文を実行する場合、実行計画を格納する既存の出力表に行を挿入するための権限が必要です。
出力する実行計画の適用対象であるSQL文を実行するための権限も必要です。このSQL文でビューにアクセスする場合は、このビューの基礎になっているすべての表およびビューへのアクセス権限が必要です。このビューが別のビューに基づき、さらにこの別のビューが、ある表に基づいている場合、別のビューとそのビューの基礎になっている表へのアクセス権限が必要です。
EXPLAIN
PLAN
で作成された実行計画を検証する場合は、出力表へ問い合せる権限が必要です。
EXPLAIN
PLAN
文はデータ操作言語(DML)文であり、データ定義言語(DDL)文ではありません。そのため、EXPLAIN
PLAN
文で加えられた変更内容は暗黙的にコミットされません。出力表のEXPLAIN
PLAN
文で生成された行を保存する場合は、この文を指定したトランザクションをコミットする必要があります。
構文
explain_plan::=
セマンティクス
SET STATEMENT_ID句
実行計画が出力される表の中で、この実行計画に該当する行にあるSTATEMENT_ID
列の値を指定します。この値によって、実行計画の行を出力表の中の他の行と区別できます。ユーザーの出力表に多数の実行計画の行が含まれている場合は、必ず、STATEMENT_ID
の値を指定します。この句を省略した場合、デフォルトでSTATEMENT_ID
値がNULLに設定されます。
INTO table句
出力表の名前を指定し、オプションとしてそのスキーマおよびデータベースの名前も指定します。この表は、EXPLAIN
PLAN
文を使用する前に作成しておく必要があります。
schema
を指定しない場合、表は自分のスキーマ内にあるとみなされます。
dblink
には、出力表が格納されているリモートのOracle Databaseに対するデータベース・リンクの完全な名前または名前の一部を指定します。Oracle Databaseの分散機能を使用している場合にのみ、リモート出力表を指定できます。dblink
を省略した場合、表がローカル・データベース上にあるとみなされます。データベース・リンクの参照方法の詳細は、「リモート・データベース内のオブジェクトの参照」を参照してください。
INTO
句を省略した場合、出力表は、ローカル・データベース上の自分のスキーマ内にあるPLAN_TABLE
であるとみなされます。
FOR statement句
実行計画生成の対象となるSELECT
、INSERT
、UPDATE
、DELETE
、MERGE
、CREATE
TABLE
、CREATE
INDEX
またはALTER
INDEX
... REBUILD
文を指定します。
EXPLAIN PLANのノート
EXPLAIN
PLAN
には、次のノートがあります。
-
statement
にparallel_clause
を指定した場合、結果として生成される実行計画はパラレルで実行されます。ただし、EXPLAIN
PLAN
コマンドによって計画表に実際に文が挿入されるため、ユーザーが発行したパラレルDML文は、トランザクションの最初のDML文ではなくなります。これは、トランザクション1つにつきパラレルDML文は1つというOracle Databaseの制限に違反するため、この文はシリアルで実行されます。文をパラレルで実行するには、EXPLAIN
PLAN
文をコミットまたはロールバックしてから、パラレルDML文を発行する必要があります。 -
一時表上で操作するための実行計画を判断する場合、
EXPLAIN
PLAN
は、同一セッションから実行する必要があります。これは、一時表内のデータがセッション固有であるためです。
例
EXPLAIN PLANの例
次の文は、UPDATE
文の実行計画およびコストを決定し、実行計画を記述した行をSTATEMENT_ID
値'Raise in Tokyo'とともに、指定したplan_table
表に挿入します。
EXPLAIN PLAN SET STATEMENT_ID = 'Raise in Tokyo' INTO plan_table FOR UPDATE employees SET salary = salary * 1.10 WHERE department_id = (SELECT department_id FROM departments WHERE location_id = 1700);
次のSELECT
文は、plan_table
表への問合せを実行し、実行計画およびコストを戻します。
SELECT id, LPAD(' ',2*(LEVEL-1))||operation operation, options, object_name, object_alias, position FROM plan_table START WITH id = 0 AND statement_id = 'Raise in Tokyo' CONNECT BY PRIOR id = parent_id AND statement_id = 'Raise in Tokyo' ORDER BY id;
問合せによって、次の実行計画が戻されます。
ID OPERATION OPTIONS OBJECT_NAME OBJECT_ALIAS POSITION --- -------------------- -------------------- -------------------- -------------------- -------- 0 UPDATE STATEMENT 4 1 UPDATE EMPLOYEES 1 2 INDEX RANGE SCAN EMP_DEPARTMENT_IX EMPLOYEES@UPD$1 1 3 TABLE ACCESS BY INDEX ROWID DEPARTMENTS DEPARTMENTS@SEL$1 1 4 INDEX RANGE SCAN DEPT_LOCATION_IX DEPARTMENTS@SEL$1 1
POSITION
列の1行目の値は、文のコストが4であることを示しています。
EXPLAIN PLAN: パーティション化された例
サンプル表sh.sales
は、time_id
列でパーティション化されます。パーティションsales_q3_2000
には、2000年10月1日より小さい時刻の値があり、time_id
列にローカル索引sales_time_bix
があります。
次の問合せについて考えてみます。
EXPLAIN PLAN FOR SELECT * FROM sales WHERE time_id BETWEEN :h AND '01-OCT-2000';
ここで、:h
はすでに宣言されているバインド変数を指します。EXPLAIN
PLAN
文は、PLAN_TABLE
を出力表とする次の問合せを実行します。次の問合せによって、パーティション情報などの基本的な実行計画が得られます。
SELECT operation, options, partition_start, partition_stop, partition_id FROM plan_table;