実行計画のツリーのたどり方 (実行計画の読み方#1)
これまでのエントリに記載してきたように、実行計画は階層的なツリー構造で表現 されます。 本エントリでは、実行計画の読み方のfirst stepとして、 実際の処理順序に即したツリー構造のたどり方を説明します。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'LAST'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------
SQL_ID dvv5bah5b4k51, child number 1
-------------------------------------
SELECT /*+ FULL(PA) INDEX(CH idx_chpa) USE_NL(CH) LEADING(PA) */ cid,
cname, pa.pid, pname FROM ch, pa WHERE ch.pid = pa.pid and pa.pid
= 1
Plan hash value: 3514264536
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 20 (100)| |
| 1 | NESTED LOOPS | | 10 | 40120 | 20 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL | PA | 1 | 2004 | 9 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| CH | 10 | 20080 | 11 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_CHPA | 10 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("PA"."PID"=1)
4 - access("CH"."PID"=1)
24 rows selected.
実行計画のツリー構造とオペレーションの親子関係
実行計画は、一般に複数のオペレーションから構成されます。オペレーションは、親子関係に したがってインデントして整形されたツリー構造となります。
たとえば、上記の実行計画は、NESTED LOOPS, TABLE ACCESS FULL などのオペレーション から構成されます。(オペレーションの種類と処理内容については次のエントリで説明します。)
オペレーションの親子関係についてですが、 Id=1 NESTED LOOPSは Id=2 TABLE ACCESS FULLと、Id=3 TABLE ACCESS BY INDEX ROWID の親となります。同様に Id=3 TABLE ACCESS BY INDEX ROWID Id= 4 INDEX RANGE SCAN の親となります。
Id=0 SELECT STATEMENT
↑
│行ソース
│
Id=1 NESTED LOOPS
↑ ↑
行ソース┌─────┘ └─────┐行ソース
│ │
Id=2 TABLE ACCESS FULL Id=3 TABLE ACCESS BY INDEX ROWID
↑
│行ソース
│
Id=4 INDEX RANGE SCAN
それぞれのオペレーションは、行ソースとよばれる表から取得した行データ(のサブセット)を出力します。 親オペレーションは子オペレーションの行ソースを入力として処理を行います。
概念的な説明だけではわかりにくいので、先の実行計画がどのように処理されるかを イメージしながら、読み方を説明してみましょう。
実行計画で一番最初に実行されるオペレーションを探す
まず、この実行計画で一番最初に実行される(*1) オペレーションを探します。 最も最上位のオペレーション(Id=0 SELECT STATEMENT)にポイントしてから、そのオペレーションの 子オペレーションをたどります。 子オペレーションが2つ以上ある場合は、上側に表記されたオペレーションをたどります。 子の子、子の子の子、とインデントされたオペレーションを順にたどってゆき、 子がなくなった時点でポイントしていたオペレーションが、 実行計画で一番最初に実行されるオペレーションです。
先の実行計画の例において、一番最初にオペレーションを特定するまでの手順は以下の とおりです。
- 1. 最も最上位のオペレーション(Id=0 SELECT)をポイント
- 2. Id=0 SELECTの子オペレーションはId=1 NESTED LOOPSだけなので、NESTED LOOPSをポイント
- 3. Id=1 NESTED LOOPSの子オペレーションとして、2つのオペレーション Id=2 TABLE ACCESS FULL と Id=3 TABLE ACCESS BY INDEX ROWID があるが、上側に表示されている Id=2 TABLE ACCESS FULLをたどる。
- 4. Id=2 TABLE ACCESS FULL には、子オペレーションがないため、 このオペレーションがこの実行計画で最初に実行されるオペレーションとなる
一番深くインデントされたオペレーションが必ずしも一番最初に実行される わけではないことに注意が必要です。 上記の例でも、一番深くインデントされたオペレーションである Id=4 INDEX RANGE SCAN は一番最初に実行されるオペレーションではありません。
- (*1)「実質的な意味で」一番最初に実行されるオペレーションという意味です。 形式的には、Id=0のSELECT STATEMENTが一番最初に実行されるオペレーションですが、この観点は理解するうえであまり意味がないからです。
以後のオペレーション実行順序
さて、最初に実行されるオペレーションが Id=2 TABLE ACCESS FULL であることはわかりました、以降、どのような順序でオペレーションが実行される のでしょうか。順に追っていきましょう。
- 5. Id=2 TABLE ACCESS FULL は、PA表をテーブルスキャン(全行取得)する オペレーションであり、取得した結果を親オペレーションId=1 NESTED LOOPに 渡す。
- 6. Id= 1 NESTED LOOP は、自分の子オペレーションのうち、次に実行すべき オペレーションを探す。ここでは、Id= 3 TABLE ACCESS BY INDEX ROWIDが 未実行であるため、Id= 3 TABLE ACCESS BY INDEX ROWID をポイントする。
- 7. Id= 3 TABLE ACCESS BY INDEX ROWID は自分の子オペレーションである、 Id= 4 INDEX RANGE SCAN をポイントする。
- 8. Id= 4 INDEX RANGE SCAN には子オペレーションがないため、 Id= 4 INDEX RANGE SCAN の処理を実行する。 索引IDX_CHPAをレンジスキャン(範囲検索)し、表に格納された行の識別子 である、ROWIDのリストを得て、取得した結果を親オペレーション Id= 3 TABLE ACCESS BY INDEX ROWID に渡す。
- 9. Id= 3 TABLE ACCESS BY INDEX ROWI Dは Id= 4 INDEX RANGE SCAN より得たROWIDの リストに従い、表から行データを取得し、取得した結果を親オペレーション Id= 1 NESTED LOOPに渡す。
- 10. Id= 1 NESTED LOOP のすべての子オペレーションの実行が完了したため、 自オペレーションの処理である Nested Loop 結合処理を実行して、結果を 親オペレーションId=0 SELECTに渡す。
- 11. Id=0 SELECTは擬似的なオペレーションであり、実際の処理は行わないため、ここで終了
このような順序となります。
ルール化するならば
先に説明した手順をルール化するならば、以下のようにまとめられます。 (わかりやすくするため厳密性を犠牲にしています。)
- 1. 自オペレーションの処理は、すべての子オペレーションの処理が完了してから実行される。
- 2. 子オペレーションがない場合、自オペレーションを実行できる。
- 3. あるオペレーションに子オペレーションが複数ある場合、上側に記載された子 オペレーションが先に実行される。

June 29th, 2011 at 11:43 pm
[...] « SQLチューニングアドバイザの代用品としての動的サンプリング 実行計画のツリーのたどり方 (実行計画の読み方#1) [...]