説明
このステートメントは、SQLステートメントの実行計画を解釈するために使用されます。対象となるのは SELECT、DELETE、INSERT、REPLACE、または UPDATE ステートメントです。
EXPLAIN は DESCRIBE および DESC の同義語です。
構文
/*テーブルまたは列の情報を取得する*/
{EXPLAIN | DESCRIBE | DESC} table_name [column_name];
/*SQL実行計画の情報を取得する*/
{EXPLAIN [INTO table_name] [SET STATEMENT_ID = 'string']
| DESCRIBE
| DESC} [explain_type] [PRETTY | PRETTY_COLOR] dml_statement;
explain_type:
BASIC
| OUTLINE
| EXTENDED
| EXTENDED_NOADDR
| PARTITIONS
| FORMAT = {TRADITIONAL| JSON}
dml_statement:
SELECT statement
| DELETE statement
| INSERT statement
| UPDATE statement
| MERGE statement
パラメータの説明
パラメータ |
説明 |
|---|---|
| table_name | テーブル名を指定します。 |
| column_name | テーブルの列名を指定します。 |
| INTO table_name | EXPLAIN の実行計画情報を指定したテーブルに保存することを示します。INTO table_name を指定しない場合、デフォルトで PLAN_TABLE テーブルに保存されます。 |
| SET STATEMENT_ID = 'string' | 現在のクエリに文字列タグを使用し、後からこのSQLの実行計画情報を検索しやすくすることを示します。SET statement_id を指定しない場合、デフォルトで空文字列がタグとして使用されます。 |
| PRETTY | PRETTY_COLOR | 実行計画ツリー内の親ノードと子ノードを線または色付きの線で結び、実行計画をより読みやすく表示します。 |
| explain_type | 解釈タイプを指定します。 |
| BASIC | 出力計画の基本情報(演算子ID、演算子名、参照テーブル名など)を指定します。 |
| OUTLINE | 出力する計画情報にアウトライン情報を含めることを指定します。 |
| EXTENDED | EXPLAIN が追加情報を生成します。これには、各演算子の入力列と出力列、テーブルへのアクセスパーティション情報、現在使用中のフィルター情報が含まれます。現在の演算子がインデックスを使用している場合、使用されているインデックス列と抽出されたQuery Rangeを表示します。 |
| EXTENDED_NOADDR | 追加情報を簡潔な形式で表示します。 |
| PARTITIONS | パーティション関連情報を表示します。 |
| TRADITIONAL | JSON | EXPLAIN の出力形式を指定します。
|
| dml_statement | DML文です。 |
例
例1:テストテーブルを作成する
-- テストテーブルtestを作成
CREATE TABLE test (
statement_id VARCHAR(30),
plan_id INT,
gmt_create TIMESTAMP,
remarks VARCHAR(4000),
operator VARCHAR(255),
options VARCHAR(255),
object_node VARCHAR(40),
object_owner VARCHAR(128),
object_name VARCHAR(128),
object_alias VARCHAR(261),
object_instance INT,
object_type VARCHAR(30),
optimizer VARCHAR(4000),
search_columns INT,
id INT,
parent_id INT,
depth INT,
position INT,
is_last_child INT,
cost INT,
cardinality INT,
bytes INT,
rowset INT,
other_tag VARCHAR(4000),
partition_start VARCHAR(4000),
partition_stop VARCHAR(4000),
partition_id INT,
other VARCHAR(4000),
distribution VARCHAR(64),
cpu_cost INT,
io_cost INT,
temp_space INT,
access_predicates VARCHAR(4000),
filter_predicates VARCHAR(4000),
startup_predicates VARCHAR(4000),
projection VARCHAR(4000),
special_predicates VARCHAR(4000),
time INT,
qblock_name VARCHAR(128),
other_xml VARCHAR(4000)
);
-- テストテーブルt1を作成
CREATE TABLE t1(c1 INT);
-- タイムスタンプのフォーマットを設定
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';
例2:実行計画をテーブルに保存する
-- 実行計画をtestテーブルに保存
EXPLAIN INTO test SELECT COUNT(*) FROM t1;
実行結果:
=================================================
|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)|
-------------------------------------------------
|0 |SCALAR GROUP BY | |1 |2 |
|1 |└─TABLE FULL SCAN|T1 |1 |2 |
=================================================
Outputs & filters:
-------------------------------------
0 - output([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=256
group(nil), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT(*))])
1 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256
access(nil), partitions(p0)
is_index_back=false, is_global_index=false,
range_key([T1.__pk_increment]), range(MIN ; MAX)always true
例3:STATEMENT_IDを使用して実行計画を識別する
-- statement_idを使用して実行計画を識別する
EXPLAIN INTO test SET STATEMENT_ID='test2' SELECT COUNT(*) FROM t1;
-- 指定されたstatement_idの実行計画を確認する
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(table_name=>'test', statement_id=>'test2'));
例4:テストテーブルを作成し、テーブル構造を確認する
-- テストテーブルを作成する
CREATE TABLE t101(c1 INT, c2 INT);
CREATE TABLE t102(c1 INT, c2 INT);
-- テーブル構造を確認する
EXPLAIN t101;
実行結果:
+-------+------------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA |
+-------+------------+------+-----+---------+-------+
| C1 | NUMBER(38) | YES | NULL | NULL | NULL |
| C2 | NUMBER(38) | YES | NULL | NULL | NULL |
+-------+------------+------+-----+---------+-------+
例5:テーブル列情報を確認する
-- テーブルt102のc2列情報を確認する
EXPLAIN t102 c2;
実行結果:
+-------+------------+------+-----+---------+-------+
| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA |
+-------+------------+------+-----+---------+-------+
| C2 | NUMBER(38) | YES | NULL | NULL | NULL |
+-------+------------+------+-----+---------+-------+
例6:explain_typeを省略する
-- explain_typeを省略してSELECTステートメントの実行計画を確認する
EXPLAIN SELECT * FROM t101, t102 WHERE t101.c2 = t102.c2;
| Query Plan |
+------------------------------------------------------------------------------------+
| ================================================= |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------- |
| |0 |HASH JOIN | |1 |8 | |
| |1 |├─TABLE FULL SCAN|T102|1 |4 | |
| |2 |└─TABLE FULL SCAN|T101|1 |4 | |
| ================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([T101.C1], [T101.C2], [T102.C1], [T102.C2]), filter(nil), rowset=16 |
| equal_conds([T101.C2 = T102.C2]), other_conds(nil) |
| 1 - output([T102.C2], [T102.C1]), filter([T102.C1 > 4]), rowset=16 |
| access([T102.C2], [T102.C1]), partitions(p0) |
| is_index_back=false, is_global_index=false, filter_before_indexback[false], |
| range_key([T102.__pk_increment]), range(MIN ; MAX)always true |
| 2 - output([T101.C2], [T101.C1]), filter(nil), rowset=16 |
| access([T101.C2], [T101.C1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T101.__pk_increment]), range(MIN ; MAX)always true |
+------------------------------------------------------------------------------------+
EXTENDED_NOADDRキーワードで追加情報を出力します。obclient> EXPLAIN EXTENDED_NOADDR SELECT * FROM t101,t102 WHERE t101.c2=t102.c2 AND t102.c1 > 4; +------------------------------------------------------------------------------------+ | Query Plan | +------------------------------------------------------------------------------------+ | ================================================= | | |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| | | ------------------------------------------------- | | |0 |HASH JOIN | |1 |8 | | | |1 |├─TABLE FULL SCAN|T102|1 |4 | | | |2 |└─TABLE FULL SCAN|T101|1 |4 | | | ================================================= | | Outputs & filters: | | ------------------------------------- | | 0 - output([T101.C1], [T101.C2], [T102.C1], [T102.C2]), filter(nil), rowset=16 | | equal_conds([T101.C2 = T102.C2]), other_conds(nil) | | 1 - output([T102.C2], [T102.C1]), filter([T102.C1 > 4]), rowset=16 | | access([T102.C2], [T102.C1]), partitions(p0) | | is_index_back=false, is_global_index=false, filter_before_indexback[false], | | range_key([T102.__pk_increment]), range(MIN ; MAX)always true | | 2 - output([T101.C2], [T101.C1]), filter(nil), rowset=16 | | access([T101.C2], [T101.C1]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([T101.__pk_increment]), range(MIN ; MAX)always true | | Used Hint: | | ------------------------------------- | | /*+ | | | | */ | | Qb name trace: | | ------------------------------------- | | stmt_id:0, stmt_type:T_EXPLAIN | | stmt_id:1, SEL$1 | | Outline Data: | | ------------------------------------- | | /*+ | | BEGIN_OUTLINE_DATA | | LEADING(@"SEL$1" ("SYS"."T102"@"SEL$1" "SYS"."T101"@"SEL$1")) | | USE_HASH(@"SEL$1" "SYS"."T101"@"SEL$1") | | FULL(@"SEL$1" "SYS"."T102"@"SEL$1") | | FULL(@"SEL$1" "SYS"."T101"@"SEL$1") | | OPTIMIZER_FEATURES_ENABLE('4.0.0.0') | | END_OUTLINE_DATA | | */ | | Optimization Info: | | ------------------------------------- | | T102: | | table_rows:1 | | physical_range_rows:1 | | logical_range_rows:1 | | index_back_rows:0 | | output_rows:0 | | table_dop:1 | | dop_method:Table DOP | | avaiable_index_name:[T102] | | stats version:0 | | dynamic sampling level:1 | | T101: | | table_rows:1 | | physical_range_rows:1 | | logical_range_rows:1 | | index_back_rows:0 | | output_rows:1 | | table_dop:1 | | dop_method:Table DOP | | avaiable_index_name:[T101] | | stats version:0 | | dynamic sampling level:1 | | Plan Type: | | LOCAL | | Note: | | Degree of Parallelisim is 1 because of table property | +------------------------------------------------------------------------------------+TRADITIONALフォーマットのINSERTステートメントの実行計画を表示します。obclient> EXPLAIN FORMAT=TRADITIONAL INSERT INTO T101 VALUES(1,1); +----------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +----------------------------------------------------------------------------------------------------------------------------------------+ | ================================================== | | |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| | | -------------------------------------------------- | | |0 |DISTRIBUTED INSERT| |1 |13 | | | |1 |└─EXPRESSION | |1 |1 | | | ================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil) | | columns([{T101: ({T101: (T101.__pk_increment, T101.C1, T101.C2)})}]), | | column_values([T_HIDDEN_PK], [column_conv(NUMBER,PS:(-1,0),NULL,__values.C1)], [column_conv(NUMBER,PS:(-1,0),NULL,__values.C2)]) | | 1 - output([__values.C1], [__values.C2]), filter(nil) | | values({1, 1}) | +----------------------------------------------------------------------------------------------------------------------------------------+JSONフォーマットのSELECTステートメントの実行計画を表示します。obclient> EXPLAIN FORMAT=JSON SELECT * FROM t101,t102 WHERE t101.c2=t102.c2 AND t102.c1 > 4; +------------------------------------------------------------------+ | Query Plan | +------------------------------------------------------------------+ | { | | "ID":0, | | "OPERATOR":"HASH JOIN ", | | "NAME":"", | | "EST.ROWS":1, | | "EST.TIME(us)":8, | | "output":"output([T101.C1], [T101.C2], [T102.C1], [T102.C2])", | | "CHILD_1": { | | "ID":1, | | "OPERATOR":"TABLE FULL SCAN", | | "NAME":"T102", | | "EST.ROWS":1, | | "EST.TIME(us)":4, | | "output":"output([T102.C2], [T102.C1])" | | }, | | "CHILD_2": { | | "ID":2, | | "OPERATOR":"TABLE FULL SCAN", | | "NAME":"T101", | | "EST.ROWS":1, | | "EST.TIME(us)":4, | | "output":"output([T101.C2], [T101.C1])" | | } | | } | +------------------------------------------------------------------+