Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Oracleの実行計画を読んでみよう! #dbts2017

db tech showcase 2017 tokyo
2017年9月7日(木) 14:30~15:20 入門者向けセミナー
Oracleの実行計画を読んでみよう! の資料です。

  • Login to see the comments

Oracleの実行計画を読んでみよう! #dbts2017

  1. 1. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 1Copyright © 2017 CO-Sol Inc. All Rights Reserved. 2017年9月7日 株式会社コーソル 渡部 亮太 Oracle入門セミナー 実行計画を読んでみよう!
  2. 2. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 2 自己紹介+所属会社紹介 • 渡部 亮太(わたべ りょうた) – JPOUG 共同創設者、ボードメンバー – 日本に8名しかいないOracle ACEの一人 – 著書「Oracleの基本」9月22日発売! 「プロとしてのOracleアーキテクチャ入門[第2版]」 – ブログ「コーソルDatabaseエンジニアのBlog」 http://cosol.jp/techdb/ • 株式会社コーソル – 「CO-Solutions=共に解決する」の理念のもと、Oracle技術に特 化した事業を展開中。心あるサービスの提供とデータベースエン ジニアの育成に注力している – 社員数: 132名 (2017年9月時点) – ORACLE MASTER Platinum 11g 取得者数 49名 ORACLE MASTER Platinum 12c 取得者数 35名 取得者数 日本 No.1 (おそらくWorld WideでNo.1) http://www.oracle.com/jp/education/omdata-171891-ja.html
  3. 3. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 3 技術者育成の取り組み [コーソル紹介] ORACLE MASTER Platinum取得者数 国内No1! 充実した教育+支援制度で技術者育成に力を入れています!
  4. 4. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 4 製品サービス 弊社ソリューションについて [コーソル紹介] 独自のサービスと製品を掛け合わせ、データベースの運用を 強力に支援致します。 &
  5. 5. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 5 [宣伝・告知] DB移行セミナーやります • 9月13日(水) 19:00-20:30 • https://connpass.com/event/63720/ • 技術領域: Oracle Database / Attunity
  6. 6. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 6 本セミナーについて • 比較的シンプルなSQLの実行計画を題材にして、Oracle Databaseの実行計画の読み方を学びます • Oracle Database初級者~中級者向けのセミナーです。 が、純粋な講義形式にしても眠くなるだけ :-P なので、 すこし対話形式のエッセンスを入れながら進めたいと思います • 途中で、実行計画を読むにあたって、落とし穴になりがちな点 についても説明します • 質問は随時Welcomeです。質疑応答が盛り上がったほうが、 みんなの理解が深まるはず! • 読みやすさ・理解しやすさのため、掲載するSQLや実行計画は 実際のもの から適宜 加工・修正しています • 同様の理由で、記述・説明の網羅性を犠牲にしているため、 キチンと理解したい場合は、マニュアルを参照してください
  7. 7. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 7 Agenda • 実行計画とは • 実行計画の取得方法 (見積ベース or 過去の実行) • ツリー構造のたどり方(実行計画の実行順序) • 基本的なオペレーションを理解する • 処理の流れをイメージできるようにする • 統計値の解釈(見積値 or 実測値、累積、 starts)
  8. 8. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 8Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画とは
  9. 9. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 9 実行計画とは • 実行計画は、SQLがOracleで実行される手順を示す • 実行計画はコストベースオプティマイザ(CBO; Cost- Based Optimizer)が作成する – CBOはOracleの内部コンポーネント – オプティマイザ統計が最新でないと適切な実行計画が作成され ないことに注意 • 不適切な実行計画でSQLが実行されると、本来であれば 実現できる処理パフォーマンスを得られない --------------------------------------------------------------------- | Id | Operation | Name | Rows |...| Time | --------------------------------------------------------------------- | 0 | SELECT STATEMENT | | |...| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 |...| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 16 |...| 00:00:01 | ---------------------------------------------------------------------
  10. 10. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 10 実行計画に含まれる情報 PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- SQL_ID 3hrvf65nm048d, child number 0 ------------------------------------- SELECT * from tab0 WHERE col_idx = 'A' Plan hash value: 2195618789 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 7 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 | 32160 | 7 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 16 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') ツリー構造をしたステップ 各ステップの統計値 補足情報 ステップ 実行計画の実行手順における実行要素 親子関係がある ←SQL文 sql_id: SQL文の識別子(Oracleが自動的に付与) ←実行計画のハッシュ値 ※:取得方法によって、情報が表示される/され ないが異なる点に注意
  11. 11. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 11 実行計画の確認方法 確認方法 実行 計画 統計 値 備考 a EXPLAIN PLAN + DBMS_XPLAN.DISPLAY 見積 見積 SQLは実行されない b SQL実行 → DBMS_XPLAN.DISPLAY_CURSOR 実行 見積 c STATISTICS_LEVEL=ALLでSQL実行 → DBMS_XPLAN.DISPLAY_CURSOR (format=>'ALLSTATS LAST') 実行 見積 実行 見積統計と実行統計 の両方を表示 • 実行計画の正確性の観点から、 DBMS_XPLAN.DISPLAY_CURSOR を使う方法(b,c)がオススメ – 共有プール(キャッシュ領域)から実行計画および統計値を取得 • EXPLAN PLAN(a)もお手軽で便利!だけど、参考用途に 見積: Oracleが見積もった(予測した)実行計画または統計値を表示 実行: 過去のSQL実行で実際に使われた実行計画または統計値を表示
  12. 12. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 12 a) EXPLAIN PLAN + DBMS_XPLAN.DISPLAY SQL> EXPLAIN PLAN FOR SELECT * FROM tab0 WHERE col_idx = 'A'; 解析されました。 SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- Plan hash value: 2195618789 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 16 | 32160 | 7 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 | 32160 | 7 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 16 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') 14行が選択されました。
  13. 13. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 13 b) SQL実行 → DBMS_XPLAN.DISPLAY_CURSOR SQL> set serveroutput off SQL> SELECT * from tab0 WHERE col_idx = 'A'; (略) SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR); PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------- SQL_ID 3hrvf65nm048d, child number 0 ------------------------------------- SELECT * from tab0 WHERE col_idx = 'A' Plan hash value: 2195618789 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 7 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 | 32160 | 7 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 16 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') 19行が選択されました。 sql_idの指定を省略すると直近実行した SQLの実行計画を表示 ただし set serveroutput onだとうまく 動かないことに注意
  14. 14. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 14 c) DBMS_XPLAN.DISPLAY_CURSOR (format=>'ALLSTATS LAST') SQL> set serveroutput off SQL> ALTER SESSION SET statistics_level=ALL; SQL> SELECT * from tab0 WHERE col_idx = 'A'; (略) SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST')) PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------- SQL_ID 3hrvf65nm048d, child number 0 ------------------------------------- SELECT * from tab0 WHERE col_idx = 'A' Plan hash value: 2195618789 ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 16 |00:00:00.01 | 10 | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 16 | 16 |00:00:00.01 | 10 | |* 2 | INDEX RANGE SCAN | T0_IDX | 1 | 16 | 16 |00:00:00.01 | 3 | ------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') 19行が選択されました。 LASTを指定しない と複数実行の平均値 になることに注意 実行統計(A-xxx:Actual)が表示される ※: ここではE-Rowsのみが見積統計
  15. 15. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 15Copyright © 2017 CO-Sol Inc. All Rights Reserved. 単一テーブルアクセスの オペレーション
  16. 16. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 16 オペレーションとは PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------- SQL_ID 3hrvf65nm048d, child number 0 ------------------------------------- SELECT * from tab0 WHERE col_idx = 'A' Plan hash value: 2195618789 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 7 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 | 32160 | 7 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 16 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') オペレーション 各ステップで実行される操作の種類 TABLE ACCESS FULL、 INDEX RANGE SCAN など ステップ 実行計画の実行手順における実行要素 親子関係がある
  17. 17. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 17 テーブルフルスキャン select * from tab0 where col_noix = 'A' -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 9 (100)| | |* 1 | TABLE ACCESS FULL| TAB0 | 16 | 32160 | 9 (0)| 00:00:01 | -------------------------------------------------------------------------- 1 - filter("COL_NOIX"='A') TABLE ACCESS FULL filter
  18. 18. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 18 インデックス経由のテーブルアクセス(一意) select * from tab0 where id = '1'; --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 1 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 2010 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | PK_TAB0 | 1 | | 0 (0)| | --------------------------------------------------------------------------------------- 2 - access("ID"=1) INDEX UNIQUE SCAN TABLE ACCESS BY INDEX ROWID access
  19. 19. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 19 インデックス経由のテーブルアクセス(範囲) select * from tab0 where col_idx = 'A'; ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | | 7 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 16 | 32160 | 7 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX0 | 16 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------ 2 - access("COL_IDX1"='A') INDEX RANGE SCAN TABLE ACCESS BY INDEX ROWID access
  20. 20. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 20Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画のツリー構造
  21. 21. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 21 実行計画のツリー構造 ---------------------------------- | Id | Operation | Name | ---------------------------------- | 0 | SELECT STATEMENT | | |* 1 | TABLE ACCESS FULL| TAB0 | ---------------------------------- オペレーション 各ステップで実行される操作の種類 [オペレーションの例] TABLE ACCESS FULL INDEX RANGE SCAN ステップ 実行計画の実行手順における実行要素 親子関係がある ステップの親子関係 親は子から「行」を受け取る 2つ以上の子ステップを持つことがある(オペレーションの種類による) 0: SEL 1: TAF Rows 親 子
  22. 22. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 22 ツリー構造のたどり方 • インデントが深いところから見てゆく(実行開始する) んだろうなぁ・・・という認識はあるかと思います が・・・ • [問題] 以下の実行計画で、(実質的に)最初に実行され るステップはどれでしょう? ---------------------------------------------------- | Id | Operation | Name | ---------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | |* 2 | TABLE ACCESS FULL | PA | | 3 | TABLE ACCESS BY INDEX ROWID | CH | |* 4 | INDEX RANGE SCAN | IDX_CHPA | ---------------------------------------------------- a b c
  23. 23. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 23 ツリー構造を整理 ------------------------------------------------- | Id | Operation | Name | ------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | |* 2 | TABLE ACCESS FULL | PA | | 3 | TABLE ACCESS BY INDEX ROWID| CH | |* 4 | INDEX RANGE SCAN | IDX_CHPA | ------------------------------------------------- 0: SEL 1: NL 2: TAF 3: TAIR 4: IRS
  24. 24. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 24 ツリー構造のたどり方 0: SEL 1: NL 2: TAF 3: TAIR 4: IRS 1. 最上位から親→子方向にたどってゆく 2. 複数の「子ステップ」がある場合、表形式表示で上にある「子ステッ プ」に進む 3. そのステップから、さらに親→子方向にたどってゆく 4. 最下位の「子ステップ」に到達したら、実行を開始する。 5. 実行終了したら、「親ステップ」に戻る 6. その「親ステップ」に、他の「子ステップ」がある場合、表形式表示で 上にある「子ステップ」に進み、3. へ ない場合、その「親ステップ」を実行し、その「親ステップ」の「さら に親のステップ」に戻り、6.を繰り返す
  25. 25. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 25 ツリー構造のたどり方 0: SEL 1: NL 2: TAF 3: TAIR 4: IRS 1. 最上位から親→子方向にたどってゆく 2. 複数の「子ステップ」がある場合、表形式表示で上にある「子ステッ プ」に進む 3. そのステップから、さらに親→子方向にたどってゆく 4. 最下位の「子ステップ」に到達したら、実行を開始する。 5. 実行終了したら、「親ステップ」に戻る 6. その「親ステップ」に、他の「子ステップ」がある場合、表形式表示で 上にある「子ステップ」に進み、3. へ ない場合、その「親ステップ」を実行し、その「親ステップ」の「さら に親のステップ」に戻り、6.を繰り返す
  26. 26. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 26 というわけで正解は • かならずしも、最も深いインデントのステップから実行されるわけでは ないことに注意 – きちんとした説明が面倒だからか・・・ 誤った情報が結構流布されている ------------------------------------------------- | Id | Operation | Name | ------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | |* 2 | TABLE ACCESS FULL | PA | | 3 | TABLE ACCESS BY INDEX ROWID| CH | |* 4 | INDEX RANGE SCAN | IDX_CHPA | ------------------------------------------------- 0: SEL 1: NL 2: TAF 3: TAIR 4: IRS 最初に 実行
  27. 27. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 27Copyright © 2017 CO-Sol Inc. All Rights Reserved. テーブルの結合と実行計画
  28. 28. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 28 結合とは EMPNO ENAME … DEPTNO 1001 本山三郎 2 1002 中村次郎 2 1003 山田花子 1 1004 三田海子 3 1005 山本太郎 1 1006 山田一朗 1 DEPTNO DNAME TELNO 1 金融部 0312345678 2 流通部 0312345679 3 公共部 0312345670 4 特別部 0312345677 EMPNO ENAME DNAME 1001 本山三郎 流通部 1002 中村次郎 流通部 1003 山田花子 金融部 1004 三田海子 公共部 1005 山本太郎 金融部 1006 山田一朗 金融部 [結合条件] emp.deptno = dept.deptno empテーブル (従業員) deptテーブル (部署) [SQL] SELECT empno, ename, dname FROM emp JOIN dept ON emp.deptno = dept.deptno;
  29. 29. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 29 結合の種類と実行計画 ネステッドループ結合 ------------------------------------------------- | Id | Operation | Name | ------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | | 2 | TABLE ACCESS BY INDEX ROWID| PA | |* 3 | INDEX UNIQUE SCAN | PK_PA | | 4 | TABLE ACCESS BY INDEX ROWID| CH | |* 5 | INDEX RANGE SCAN | IDX_CHPA | ------------------------------------------------- ソートマージ結合 ------------------------------------ | Id | Operation | Name | ------------------------------------ | 0 | SELECT STATEMENT | | | 1 | MERGE JOIN | | | 2 | SORT JOIN | | |* 3 | TABLE ACCESS FULL| T1 | |* 4 | SORT JOIN | | | 5 | TABLE ACCESS FULL| T2 | ------------------------------------ ハッシュ結合 ------------------------------------------ | Id | Operation | Name | ------------------------------------------ | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN | | | 2 | TABLE ACCESS FULL | DEPARTMENTS | | 3 | TABLE ACCESS FULL | EMPLOYEES | ------------------------------------------ • 結合データ量=小で選択されやすい • 通常インデックスとともに使われる • Oracleのバージョンにより細かい違いが ある • 結合データ量=大で選択されやすい • 通常テーブルフルスキャンとともに使われる • 結合条件が等価結合でのみ選択される • 選択されるケースは少なめ
  30. 30. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 30Copyright © 2017 CO-Sol Inc. All Rights Reserved. ネステッドループ結合の 実行計画を読んでみる
  31. 31. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 31 実行計画を読む手順 1. インデント表形式からツリー構造をイメージ 2. ツリー構造の実行順序を理解 3. オペレーションと実行順序から、各ステップの処理内容 をイメージ ※:1. 2. は先行して説明済み
  32. 32. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 32 今回とりあげる実行計画 SQL_ID byzfsqntmu2h5, child number 0 ------------------------------------- SELECT /*+ 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: 1035406045 ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.09 | 15 | 14 | | 1 | NESTED LOOPS | | 1 | 10 | 10 |00:00:00.09 | 15 | 14 | | 2 | TABLE ACCESS BY INDEX ROWID| PA | 1 | 1 | 1 |00:00:00.04 | 2 | 2 | |* 3 | INDEX UNIQUE SCAN | PK_PA | 1 | 1 | 1 |00:00:00.02 | 1 | 1 | | 4 | TABLE ACCESS BY INDEX ROWID| CH | 1 | 10 | 10 |00:00:00.05 | 13 | 12 | |* 5 | INDEX RANGE SCAN | IDX_CHPA | 1 | 10 | 10 |00:00:00.01 | 3 | 2 | ------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("PA"."PID"=1) 5 - access("CH"."PID"=1) 詳しい人向けの補足 12cから導入された最適化機能Batch table access by rowidをOFFにした実行計画
  33. 33. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 33 1. インデント表形式からツリー構造をイメージ ---------------------------------------------------------- | Id | Operation | Name | Starts | ---------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 | NESTED LOOPS | | 1 | | 2 | TABLE ACCESS BY INDEX ROWID| PA | 1 | |* 3 | INDEX UNIQUE SCAN | PK_PA | 1 | | 4 | TABLE ACCESS BY INDEX ROWID| CH | 1 | |* 5 | INDEX RANGE SCAN | IDX_CHPA | 1 | ---------------------------------------------------------- 3 - access("PA"."PID"=1) 5 - access("CH"."PID"=1) 0: SEL 1: NL 2: TAIR 4: TAIR 5: IRS 3: IUS
  34. 34. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 34 2. ツリー構造の実行順序を理解 ---------------------------------------------------------- | Id | Operation | Name | Starts | ---------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 | NESTED LOOPS | | 1 | | 2 | TABLE ACCESS BY INDEX ROWID| PA | 1 | |* 3 | INDEX UNIQUE SCAN | PK_PA | 1 | | 4 | TABLE ACCESS BY INDEX ROWID| CH | 1 | |* 5 | INDEX RANGE SCAN | IDX_CHPA | 1 | ---------------------------------------------------------- 3 - access("PA"."PID"=1) 5 - access("CH"."PID"=1) 0: SEL 1: NL 2: TAIR 4: TAIR 5: IRS 3: IUS 最初に 実行
  35. 35. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 35 3. 各ステップの処理内容をイメージ INDEX RANGE SCAN TABLE ACCESS BY INDEX ROWID NL TABLE ACCESS BY INDEX ROWID INDEX UNIQUE SCAN ------------------------------------------------- | Id | Operation | Name | ------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | | 2 | TABLE ACCESS BY INDEX ROWID| PA | |* 3 | INDEX UNIQUE SCAN | PK_PA | | 4 | TABLE ACCESS BY INDEX ROWID| CH | |* 5 | INDEX RANGE SCAN | IDX_CHPA | ------------------------------------------------- 3 - access("PA"."PID"=1) 5 - access("CH"."PID"=1) PK_PA PA IDX_CHPA CH 0: SEL 1: NL 2: TAIR 4: TAIR 5: IRS 3: IUS
  36. 36. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 36Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画の統計値を理解する
  37. 37. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 37 実行計画 各ステップの統計値 • 各ステップの統計値が表示される – 統計値ごとに解釈が異なる : 下位ステップを含めた累積 or そのステップ単体 • 見積統計と実行統計の2種類がある SELECT * FROM tab0 WHERE col_idx = 'A' AND col_noix='B' -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 2 (100)| | |* 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 2010 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 3 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- 1 - filter("COL_NOIX"='B') 2 - access("COL_IDX"='A') 各ステップの統計値
  38. 38. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 38 統計値とその解釈 統計値 解釈・意味 累積? Rows そのステップが上位のステップに返す見積行数 N Bytes そのステップが上位のステップに返すRowsの見積バイト数 N Cost そのステップ以下のステップの累積コスト コスト=平たく言うと「オラクルが予測した処理時間(単位なし)」 Y Time そのステップ以下のステップの予想処理時間 Y SELECT * FROM tab0 WHERE col_idx = 'A' AND col_noix='B' -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 2 (100)| | |* 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 2010 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IDX | 3 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- 1 - filter("COL_NOIX"='B') 2 - access("COL_IDX"='A') 0: SEL 1: TIR 2:IRS Rows=1 Rows=3
  39. 39. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 39 処理フローとRows統計 INDEX RANGE SCAN TABLE ACCESS BY INDEX ROWID t0_IDX TAB0 SELECT * from tab0 WHERE col_idx = 'A' AND col_noix='B' ------------------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------------------ | 0 | SELECT STATEMENT | | | |* 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | |* 2 | INDEX RANGE SCAN | T0_IDX | 3 | ------------------------------------------------------ 1 - filter("COL_NOIX"='B') 2 - access("COL_IDX"='A') filter access 0: SEL 1: TIR 2:IRS Rows=1 Rows=3
  40. 40. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 40 SQLチューニングとRows統計 • SQLチューニングの1つの指標 実行計画の早い段階で、データを絞り込む → 大量のデータを引き回す必要がなくなるので、処理の 高速化に寄与する • すなわち、Rows統計は小さい値であることが望ましい。 できれば、実行計画の早い段階で、小さい値にできるこ とが望ましい • ただ・・・「Rows統計」は見積統計であることに注意 実行統計である「A-Rows」を用いる方がより適切 (見積統計と実行統計については後述) • さらにもう一つ・・・(次ページ)
  41. 41. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 41 Rows統計の注意点 • 明らかにアクセスしたデータ量が異なるのに、 両方ともRows=1とは?? • Rowsはそのステップが上位ステップに引き渡す行数を示す SELECT * from t9 WHERE id = 1 ----------------------------------------------------- | Id | Operation | Name | Rows | ----------------------------------------------------- | 0 | SELECT STATEMENT | | | | 1 | TABLE ACCESS BY INDEX ROWID| T9 | 1 | |* 2 | INDEX UNIQUE SCAN | PK_T9 | 1 | ----------------------------------------------------- SELECT * from t9 WHERE id = 1 ------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------ | 0 | SELECT STATEMENT | | 1 | |* 1 | TABLE ACCESS FULL| T9 | 1 | ------------------------------------------ TABLE ACCESS FULL filterINDEX UNIQUE SCAN TABLE ACCESS BY INDEX ROWID access
  42. 42. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 42Copyright © 2017 CO-Sol Inc. All Rights Reserved. 見積統計と実行統計
  43. 43. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 43 実行計画確認方法と見積統計、実行統計 • 確認方法cでのみ、SQL実行における「本当の」統計値を 得られる • 確認方法a、bで得られる統計値は、あくまでも「Oracle が予測した」統計値であることに注意 確認方法 実行 計画 統計 備考 a EXPLAIN PLAN + DBMS_XPLAN.DISPLAY 見積 見積 SQLは実行されない b SQL実行 → DBMS_XPLAN.DISPLAY_CURSOR 実行 見積 c STATISTICS_LEVEL=ALLでSQL実行 → DBMS_XPLAN.DISPLAY_CURSOR (format=>'ALLSTATS LAST') 実行 見積 実行 見積統計と実行統計 の両方を表示
  44. 44. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 44 c) DBMS_XPLAN.DISPLAY_CURSOR (format=>'ALLSTATS LAST') SQL> ALTER SESSION SET statistics_level=ALL; SQL> SELECT * from tab0 WHERE col_idx = 'A'; (略) SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST')) PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------- SQL_ID 3hrvf65nm048d, child number 0 ------------------------------------- SELECT * from tab0 WHERE col_idx = 'A' Plan hash value: 2195618789 ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 16 |00:00:00.01 | 10 | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 16 | 16 |00:00:00.01 | 10 | |* 2 | INDEX RANGE SCAN | T0_IDX | 1 | 16 | 16 |00:00:00.01 | 3 | ------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL_IDX"='A') 19行が選択されました。
  45. 45. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 45 見積統計と実行統計 (E-xxxとA-xxx) ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 16 |00:00:00.01 | 10 | | 1 | TABLE ACCESS BY INDEX ROWID| TAB0 | 1 | 16 | 16 |00:00:00.01 | 10 | |* 2 | INDEX RANGE SCAN | T0_IDX | 1 | 16 | 16 |00:00:00.01 | 3 | ------------------------------------------------------------------------------------------------ 統計の種類 見積統計(E-xxx) Oracleが見積もった(予測した)統計値 実行統計 (A-xxx、Starts、 Buffersなど) 過去のSQL実行における実際の統計値
  46. 46. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 46 見積統計と実行統計が異なる例 SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST')); ----------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 4 | | 1 | TABLE ACCESS BY INDEX ROWID| T0 | 1 | 250 | 1 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN | T0_IX | 1 | 250 | 1 |00:00:00.01 | 3 | ----------------------------------------------------------------------------------------------- SQL> EXPLAIN PLAN FOR SELECT * FROM t0 WHERE col_idx = 'A'; SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); : ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 250 | 489K| 85 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T0 | 250 | 489K| 85 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IX | 250 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------- SQL> SELECT col_idx, count(*) FROM t0 GROUP BY col_idx; C COUNT(*) - ---------- A 1 B 1 C 1 X 997
  47. 47. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 47 見積統計と実行統計が異なることの意味 • Oracleが見積に失敗していることを示す • 対処策:より正確な見積ができるように、それを支援す る情報を追加する → オプティマイザ統計を改善する SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST')); ----------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 4 | | 1 | TABLE ACCESS BY INDEX ROWID| T0 | 1 | 250 | 1 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN | T0_IX | 1 | 250 | 1 |00:00:00.01 | 3 | -----------------------------------------------------------------------------------------------
  48. 48. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 48 オプティマイザ統計の改善による解決 SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(null, 't0', method_opt => 'FOR COLUMNS SIZE AUTO col_idx'); PL/SQLプロシージャが正常に完了しました。 SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST')); ----------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 4 | | 1 | TABLE ACCESS BY INDEX ROWID| T0 | 1 | 1 | 1 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN | T0_IX | 1 | 1 | 1 |00:00:00.01 | 3 | ----------------------------------------------------------------------------------------------- SQL> EXPLAIN PLAN FOR SELECT * FROM t0 WHERE col_idx = 'A'; SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); : ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2007 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T0 | 1 | 2007 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T0_IX | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------- • ヒストグラムの収集で解決 • ヒストグラム=列値の頻度情報
  49. 49. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 49Copyright © 2017 CO-Sol Inc. All Rights Reserved. Starts実行統計
  50. 50. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 50 Starts実行統計 : オペレーションの実行回数 • 実行計画(見積)では表示されないが、実行計画を理解 する助けになるときがある SELECT cid, cname, pa.pid, pname FROM ch, pa WHERE ch.pid = pa.pid and pa.pid IN (1,2,3) ------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | ------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 3 | | 1 | NESTED LOOPS | | 1 | 3 | 3 | |* 2 | TABLE ACCESS FULL | CH | 1 | 3 | 3 | | 3 | TABLE ACCESS BY INDEX ROWID| PA | 3 | 1 | 3 | |* 4 | INDEX UNIQUE SCAN | PK_PA | 3 | 1 | 3 | ------------------------------------------------------------------------- 0: SEL 1: NL 2: TAF 4: TAIR 5: IUS Starts=3 → 3回実行
  51. 51. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 51 Starts実行統計 : オペレーションの実行回数 SELECT cid, cname, pa.pid, pname FROM ch, pa WHERE ch.pid = pa.pid and pa.pid IN (1,2,3) ------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | ------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 3 | | 1 | NESTED LOOPS | | 1 | 3 | 3 | |* 2 | TABLE ACCESS FULL | CH | 1 | 3 | 3 | | 3 | TABLE ACCESS BY INDEX ROWID| PA | 3 | 1 | 3 | |* 4 | INDEX UNIQUE SCAN | PK_PA | 3 | 1 | 3 | ------------------------------------------------------------------------- INDEX UNIQUE SCAN TABLE ACCESS BY INDEX ROWID NL TABLE ACCESS FULL CH PK_PA PA access ① ② ③ 0: SEL 1: NL 2: TAF 4: TAIR 5: IUS Starts=3 → 3回実行 ① ② ③ ① ② ③
  52. 52. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 52 Questions & Answers
  53. 53. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 53

×