SlideShare a Scribd company logo
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 1Copyright © 2017 CO-Sol Inc. All Rights Reserved.
2017年9月7日
株式会社コーソル 渡部 亮太
Oracle入門セミナー
実行計画を読んでみよう!
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 3
技術者育成の取り組み [コーソル紹介]
ORACLE MASTER Platinum取得者数 国内No1!
充実した教育+支援制度で技術者育成に力を入れています!
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 4
製品サービス
弊社ソリューションについて [コーソル紹介]
独自のサービスと製品を掛け合わせ、データベースの運用を
強力に支援致します。
&
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 5
[宣伝・告知] DB移行セミナーやります
• 9月13日(水) 19:00-20:30
• https://connpass.com/event/63720/
• 技術領域: Oracle Database / Attunity
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 6
本セミナーについて
• 比較的シンプルなSQLの実行計画を題材にして、Oracle
Databaseの実行計画の読み方を学びます
• Oracle Database初級者~中級者向けのセミナーです。
が、純粋な講義形式にしても眠くなるだけ :-P なので、
すこし対話形式のエッセンスを入れながら進めたいと思います
• 途中で、実行計画を読むにあたって、落とし穴になりがちな点
についても説明します
• 質問は随時Welcomeです。質疑応答が盛り上がったほうが、
みんなの理解が深まるはず!
• 読みやすさ・理解しやすさのため、掲載するSQLや実行計画は
実際のもの から適宜 加工・修正しています
• 同様の理由で、記述・説明の網羅性を犠牲にしているため、
キチンと理解したい場合は、マニュアルを参照してください
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 7
Agenda
• 実行計画とは
• 実行計画の取得方法 (見積ベース or 過去の実行)
• ツリー構造のたどり方(実行計画の実行順序)
• 基本的なオペレーションを理解する
• 処理の流れをイメージできるようにする
• 統計値の解釈(見積値 or 実測値、累積、 starts)
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 8Copyright © 2017 CO-Sol Inc. All Rights Reserved.
実行計画とは
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 |
---------------------------------------------------------------------
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が自動的に付与)
←実行計画のハッシュ値
※:取得方法によって、情報が表示される/され
ないが異なる点に注意
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実行で実際に使われた実行計画または統計値を表示
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行が選択されました。
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だとうまく
動かないことに注意
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のみが見積統計
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 15Copyright © 2017 CO-Sol Inc. All Rights Reserved.
単一テーブルアクセスの
オペレーション
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 など
ステップ
実行計画の実行手順における実行要素
親子関係がある
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
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
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 20Copyright © 2017 CO-Sol Inc. All Rights Reserved.
実行計画のツリー構造
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
親 子
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
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 24
ツリー構造のたどり方
• 最上位からインデントが深い方向にたどってゆく
• 同じインデントのステップがある場合、表形式表示で上のステップを先
に実行する
• それよりインデントが深いステップがなくなったら、表形式表示で下の
ステップに移動する。ない場合は浅いインデント
-------------------------------------------------
| 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
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.を繰り返す
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
最初に
実行
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 27Copyright © 2017 CO-Sol Inc. All Rights Reserved.
テーブルの結合と実行計画
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;
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のバージョンにより細かい違いが
ある
• 結合データ量=大で選択されやすい
• 通常テーブルフルスキャンとともに使われる
• 結合条件が等価結合でのみ選択される
• 選択されるケースは少なめ
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 30Copyright © 2017 CO-Sol Inc. All Rights Reserved.
ネステッドループ結合の
実行計画を読んでみる
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 31
実行計画を読む手順
1. インデント表形式からツリー構造をイメージ
2. ツリー構造の実行順序を理解
3. オペレーションと実行順序から、各ステップの処理内容
をイメージ
※:1. 2. は先行して説明済み
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にした実行計画
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
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
最初に
実行
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 36Copyright © 2017 CO-Sol Inc. All Rights Reserved.
実行計画の統計値を理解する
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')
各ステップの統計値
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
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 40
SQLチューニングとRows統計
• SQLチューニングの1つの指標
実行計画の早い段階で、データを絞り込む
→ 大量のデータを引き回す必要がなくなるので、処理の
高速化に寄与する
• すなわち、Rows統計は小さい値であることが望ましい。
できれば、実行計画の早い段階で、小さい値にできるこ
とが望ましい
• ただ・・・「Rows統計」は見積統計であることに注意
実行統計である「A-Rows」を用いる方がより適切
(見積統計と実行統計については後述)
• さらにもう一つ・・・(次ページ)
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
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 42Copyright © 2017 CO-Sol Inc. All Rights Reserved.
見積統計と実行統計
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')
実行 見積
実行
見積統計と実行統計
の両方を表示
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行が選択されました。
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実行における実際の統計値
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
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 |
-----------------------------------------------------------------------------------------------
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 |
-------------------------------------------------------------------------------------
• ヒストグラムの収集で解決
• ヒストグラム=列値の頻度情報
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 49Copyright © 2017 CO-Sol Inc. All Rights Reserved.
Starts実行統計
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回実行
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回実行
①
②
③
① ② ③
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 52
Questions
&
Answers
Copyright © 2017 CO-Sol Inc. All Rights Reserved. 53

More Related Content

PDF
JDKの選択肢とサーバーサイドでの選び方
PDF
Oracle GoldenGate 19c を使用した 簡単データベース移行ガイド_v1.0
PDF
Oracle GoldenGate FAQ
PDF
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
PDF
しばちょう先生による特別講義! RMANバックアップの運用と高速化チューニング
PDF
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
PDF
ML2/OVN アーキテクチャ概観
JDKの選択肢とサーバーサイドでの選び方
Oracle GoldenGate 19c を使用した 簡単データベース移行ガイド_v1.0
Oracle GoldenGate FAQ
Memoizeの仕組み(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
Oracle GoldenGateでの資料採取(トラブル時に採取すべき資料)
しばちょう先生による特別講義! RMANバックアップの運用と高速化チューニング
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
ML2/OVN アーキテクチャ概観

What's hot (20)

PDF
コンテナ未経験新人が学ぶコンテナ技術入門
PDF
Ethernetの受信処理
PDF
Oracle GoldenGate アーキテクチャと基本機能
PPTX
本当は恐ろしい分散システムの話
PPTX
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PDF
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
PDF
ストリーム処理を支えるキューイングシステムの選び方
PPTX
やってはいけない空振りDelete
PPTX
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
PDF
Dockerを支える技術
PDF
Oracle Analytics Server のご紹介【2021年3月版】
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PDF
perfを使ったPostgreSQLの解析(前編)
PDF
ソーシャルゲームのためのデータベース設計
PDF
CSI Driverを開発し自社プライベートクラウドにより適した安全なKubernetes Secrets管理を実現した話
PDF
PostgreSQLの運用・監視にまつわるエトセトラ
PDF
あなたの知らないPostgreSQL監視の世界
PDF
Oracle Spatial 概要説明資料
PDF
ZFSでストレージ
PDF
Fluentdのお勧めシステム構成パターン
コンテナ未経験新人が学ぶコンテナ技術入門
Ethernetの受信処理
Oracle GoldenGate アーキテクチャと基本機能
本当は恐ろしい分散システムの話
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
ストリーム処理を支えるキューイングシステムの選び方
やってはいけない空振りDelete
Apache Spark on Kubernetes入門(Open Source Conference 2021 Online Hiroshima 発表資料)
Dockerを支える技術
Oracle Analytics Server のご紹介【2021年3月版】
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
perfを使ったPostgreSQLの解析(前編)
ソーシャルゲームのためのデータベース設計
CSI Driverを開発し自社プライベートクラウドにより適した安全なKubernetes Secrets管理を実現した話
PostgreSQLの運用・監視にまつわるエトセトラ
あなたの知らないPostgreSQL監視の世界
Oracle Spatial 概要説明資料
ZFSでストレージ
Fluentdのお勧めシステム構成パターン
Ad

Viewers also liked (6)

PPTX
はじめてのSQLチューニング(oracle)
PDF
バックアップと障害復旧から考えるOracle Database, MySQL, PostgreSQLの違い - Database Lounge Tokyo #2
PDF
Oracle Databaseを用いて学ぶ RDBMSの基本 (抜粋版) - JPOUG Oracle Database入学式 2016
PDF
より深く知るオプティマイザとそのチューニング
PDF
Standard Edition 2でも使えるOracle Database 12c Release 2オススメ新機能
PDF
バックアップと障害復旧から考えるOracle Database, MySQL, PostgreSQLの違い
はじめてのSQLチューニング(oracle)
バックアップと障害復旧から考えるOracle Database, MySQL, PostgreSQLの違い - Database Lounge Tokyo #2
Oracle Databaseを用いて学ぶ RDBMSの基本 (抜粋版) - JPOUG Oracle Database入学式 2016
より深く知るオプティマイザとそのチューニング
Standard Edition 2でも使えるOracle Database 12c Release 2オススメ新機能
バックアップと障害復旧から考えるOracle Database, MySQL, PostgreSQLの違い
Ad

Similar to Oracleの実行計画を読んでみよう! #dbts2017 (20)

PDF
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PPT
プロとしてのOracleアーキテクチャ入門 ~番外編~
PDF
2019年度 若手技術者向け講座 実行計画
PDF
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
PDF
Introduction of Oracle Database Architecture
PDF
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
PPTX
実行統計による実践的SQLチューニング
PDF
アクセスプラン(実行計画)の読み方入門
PDF
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PDF
プロとしてのOracleアーキテクチャ入門 ~番外編~ @ Developers Summit 2009
PDF
まだ統計固定で消耗してるの? - Bind Peek をもっと使おうぜ! 2015 Edition -
PDF
2018年度 若手技術者向け講座 実行計画
PDF
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
PDF
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
PPT
20090107 Postgre Sqlチューニング(Sql編)
PPT
SQLチューニング勉強会資料
PPTX
03 kueripahuomansuchiyuninguno shou_fa_
PPTX
V$SQLとその周辺でER図を描いてみよう!
PDF
DDD 2016 DB 12c クエリー・オプティマイザ新機能活用と統計情報運用の戦略
PPTX
SQLチューニング入門 入門編
PostgreSQL実行計画入門@関西PostgreSQL勉強会
プロとしてのOracleアーキテクチャ入門 ~番外編~
2019年度 若手技術者向け講座 実行計画
Bind Peek をもっと使おうぜ!(柴田 歩) - JPOUG Advent Calendar 2014(Day 5) -
Introduction of Oracle Database Architecture
Introduction of Oracle Database Architecture(抜粋版) - JPOUG Oracle Database入学式 ...
実行統計による実践的SQLチューニング
アクセスプラン(実行計画)の読み方入門
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
プロとしてのOracleアーキテクチャ入門 ~番外編~ @ Developers Summit 2009
まだ統計固定で消耗してるの? - Bind Peek をもっと使おうぜ! 2015 Edition -
2018年度 若手技術者向け講座 実行計画
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
20090107 Postgre Sqlチューニング(Sql編)
SQLチューニング勉強会資料
03 kueripahuomansuchiyuninguno shou_fa_
V$SQLとその周辺でER図を描いてみよう!
DDD 2016 DB 12c クエリー・オプティマイザ新機能活用と統計情報運用の戦略
SQLチューニング入門 入門編

More from Ryota Watabe (6)

PDF
全社情報共有サイトへの Alfresco Community 5 導入事例紹介 - 第27回Alfresco勉強会
PDF
Corruption And Revive - db tech showcase 2013 特濃JPOUG
PDF
OSS-DB Silver ポイント解説セミナー ~SQL編~ (PostgreSQL9.0)
PDF
Analyzing Oracle Database hang issues using various diagnostics.
PDF
バッチ処理にバインド変数はもうやめません? ~|バッチ処理の突発遅延を題材にして考えてみる~
PDF
Oracle Database In Lock
全社情報共有サイトへの Alfresco Community 5 導入事例紹介 - 第27回Alfresco勉強会
Corruption And Revive - db tech showcase 2013 特濃JPOUG
OSS-DB Silver ポイント解説セミナー ~SQL編~ (PostgreSQL9.0)
Analyzing Oracle Database hang issues using various diagnostics.
バッチ処理にバインド変数はもうやめません? ~|バッチ処理の突発遅延を題材にして考えてみる~
Oracle Database In Lock

Recently uploaded (10)

PDF
商用ウェブカメラ市場:世界の産業現状、競合分析、シェア、規模、動向2025-2031年の予測
PDF
世界半導体用酸化ハフニウム市場のサプライチェーン解析:上流、下流、収益モデル分析2025-2031
PDF
グローバルロープウェイ用スチールワイヤーロープ市場2025:主要企業のシェア、売上動向、競争戦略
PDF
【QYResearch】グローバル農業機械市場の動向分析と成長戦略に関する総合調査報告
PDF
Qlik TECH TALK セミナー:What's New In Qlik ~ 2025年7月リリース最新機能のご紹介
PDF
限外ろ過膜調査レポート:市場規模、シェア、産業分析データ、最新動向2025-2031 YH Research
PDF
細胞培養用バイオリアクターおよび発酵槽市場規模の成長見通し:2031年には2823百万米ドルに到達へ
PDF
【QYResearch】グローバルコネクタ市場の動向と将来展望に関する詳細な分析報告
PDF
XCMSを用いた質量分析データ処理_BioCAsia2021_yamamoto.pdf
PDF
【QYResearch】人形ロボット産業の市場構造と今後の発展方向に関する分析レポート
商用ウェブカメラ市場:世界の産業現状、競合分析、シェア、規模、動向2025-2031年の予測
世界半導体用酸化ハフニウム市場のサプライチェーン解析:上流、下流、収益モデル分析2025-2031
グローバルロープウェイ用スチールワイヤーロープ市場2025:主要企業のシェア、売上動向、競争戦略
【QYResearch】グローバル農業機械市場の動向分析と成長戦略に関する総合調査報告
Qlik TECH TALK セミナー:What's New In Qlik ~ 2025年7月リリース最新機能のご紹介
限外ろ過膜調査レポート:市場規模、シェア、産業分析データ、最新動向2025-2031 YH Research
細胞培養用バイオリアクターおよび発酵槽市場規模の成長見通し:2031年には2823百万米ドルに到達へ
【QYResearch】グローバルコネクタ市場の動向と将来展望に関する詳細な分析報告
XCMSを用いた質量分析データ処理_BioCAsia2021_yamamoto.pdf
【QYResearch】人形ロボット産業の市場構造と今後の発展方向に関する分析レポート

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

  • 1. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 1Copyright © 2017 CO-Sol Inc. All Rights Reserved. 2017年9月7日 株式会社コーソル 渡部 亮太 Oracle入門セミナー 実行計画を読んでみよう!
  • 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 3 技術者育成の取り組み [コーソル紹介] ORACLE MASTER Platinum取得者数 国内No1! 充実した教育+支援制度で技術者育成に力を入れています!
  • 4. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 4 製品サービス 弊社ソリューションについて [コーソル紹介] 独自のサービスと製品を掛け合わせ、データベースの運用を 強力に支援致します。 &
  • 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 6 本セミナーについて • 比較的シンプルなSQLの実行計画を題材にして、Oracle Databaseの実行計画の読み方を学びます • Oracle Database初級者~中級者向けのセミナーです。 が、純粋な講義形式にしても眠くなるだけ :-P なので、 すこし対話形式のエッセンスを入れながら進めたいと思います • 途中で、実行計画を読むにあたって、落とし穴になりがちな点 についても説明します • 質問は随時Welcomeです。質疑応答が盛り上がったほうが、 みんなの理解が深まるはず! • 読みやすさ・理解しやすさのため、掲載するSQLや実行計画は 実際のもの から適宜 加工・修正しています • 同様の理由で、記述・説明の網羅性を犠牲にしているため、 キチンと理解したい場合は、マニュアルを参照してください
  • 7. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 7 Agenda • 実行計画とは • 実行計画の取得方法 (見積ベース or 過去の実行) • ツリー構造のたどり方(実行計画の実行順序) • 基本的なオペレーションを理解する • 処理の流れをイメージできるようにする • 統計値の解釈(見積値 or 実測値、累積、 starts)
  • 8. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 8Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画とは
  • 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. 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. 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. 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 15Copyright © 2017 CO-Sol Inc. All Rights Reserved. 単一テーブルアクセスの オペレーション
  • 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. 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 20Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画のツリー構造
  • 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 24 ツリー構造のたどり方 • 最上位からインデントが深い方向にたどってゆく • 同じインデントのステップがある場合、表形式表示で上のステップを先 に実行する • それよりインデントが深いステップがなくなったら、表形式表示で下の ステップに移動する。ない場合は浅いインデント ------------------------------------------------- | 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
  • 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 27Copyright © 2017 CO-Sol Inc. All Rights Reserved. テーブルの結合と実行計画
  • 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 30Copyright © 2017 CO-Sol Inc. All Rights Reserved. ネステッドループ結合の 実行計画を読んでみる
  • 31. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 31 実行計画を読む手順 1. インデント表形式からツリー構造をイメージ 2. ツリー構造の実行順序を理解 3. オペレーションと実行順序から、各ステップの処理内容 をイメージ ※:1. 2. は先行して説明済み
  • 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. 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 36Copyright © 2017 CO-Sol Inc. All Rights Reserved. 実行計画の統計値を理解する
  • 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 40 SQLチューニングとRows統計 • SQLチューニングの1つの指標 実行計画の早い段階で、データを絞り込む → 大量のデータを引き回す必要がなくなるので、処理の 高速化に寄与する • すなわち、Rows統計は小さい値であることが望ましい。 できれば、実行計画の早い段階で、小さい値にできるこ とが望ましい • ただ・・・「Rows統計」は見積統計であることに注意 実行統計である「A-Rows」を用いる方がより適切 (見積統計と実行統計については後述) • さらにもう一つ・・・(次ページ)
  • 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 42Copyright © 2017 CO-Sol Inc. All Rights Reserved. 見積統計と実行統計
  • 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. 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. 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. 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. 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 49Copyright © 2017 CO-Sol Inc. All Rights Reserved. Starts実行統計
  • 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. 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. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 52 Questions & Answers
  • 53. Copyright © 2017 CO-Sol Inc. All Rights Reserved. 53