WR blog

about Enterprise IT, Oracle Database, Jazz/Fusion Music, etc…

WR blog RSS Feed
 
 
 
 

実行計画のツリーのたどり方 (実行計画の読み方#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. あるオペレーションに子オペレーションが複数ある場合、上側に記載された子 オペレーションが先に実行される。
このエントリをはてなブックマークに登録

One Response to “実行計画のツリーのたどり方 (実行計画の読み方#1)”

  1. 1
    WR blog » 実行計画の読み方:

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

Leave a Reply

Profile

渡部亮太 / Watabe Ryota
代官山在住のOracle Database Engineer。 株式会社コーソル所属。講演/講師業もぼちぼち。書籍「プロとしてのOracle運用管理入門」「プロとしてのOracleアーキテクチャ入門」買ってくれるとうれしいなっと。 twitter:wrcsus4

Book



Other Works

Certifications

  • Oracle Master 10g Platinum
  • Oracle Master 11g Gold
  • Oracle Master Silver Oracle PL/SQL Developer
  • Oracle Master Expert 10g RAC
  • Oracle Master Expert Oracle on Linux
  • LPIC level2
  • CCNA
  • 日商簿記3級

Contact

wrcsus4 _at_ gmail _dot_ com

Archives

Recent Posts

Recent Comments

Categories

Tags

Meta