sqlチューニング勉強会資料
TRANSCRIPT
Session by Shinnosuke Akita
2016.03.30
SQL チューニング勉強会
Self Introduction秋田 進之助 (Shinnosuke Akita)
株式会社バルテック所属 4 年目 ‐ データベースの構築・トラブルシューティングなど
著書著書 「グラフ型データベース入門 」 2016 年セッションスピーカーセッションスピーカー 「 Oracle Database のバックアップを考えよう」 2015 年 @JPOUG 「 Smart Scan 奮闘記」 2014 年 @JPOUG など所属団体所属団体 JPOUG ( Japan Oracle User Group) Neo4j ユーザ会
Today’s Agenda・ SQL の流れ・実行計画について・なぜ索引は速いのか・索引の種類とオペレーション・結合の種類と特徴・ヒント句・実行計画の確認方法
・デモ
SQLの流れSQLは、どうやってDBサーバに認識され、実行されるのだろうか?
SQLが流れるまで
オープン 解析 バインド 実行 フェッチ クローズ
実行フェーズ
主な動き
解析 文の構文チェック、権限チェック、実行計画作成
バインド バインド変数のバインド
フェッチ 対象レコードをローカル変数に取り出す
実行計画とは?
解析のフェーズに含まれる。
テーブルをフルスキャン(すべて読み込む)するか、インデックスを使用するか。どのような結合を使用するかなどを解析し、計画を立てる。
オープン 解析 バインド 実行 フェッチ クローズ
ソフトパースとハードパース
オープン 解析 バインド 実行 フェッチ クローズ
SQL の実行フェーズに「解析」があるが、解析には時間がかかる。
一度作成された実行計画は Oracle の共有プールに格納され、データが入りきらなくなって追い出される(エージアウト)まで保持され、作成された計画は再利用される。共有プールを節約するために、 WHERE 句の値をバインド変数化することも有効である。 ( 例 ) WHERE SYAINNO = :a;
実行計画を見てみよう実行計画 ---------------------------------------------------------- Plan hash value: 2520579295 ------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| TEST2_IX1 | 1 | 4 | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("NUM"=1)
実行する処理が表示される。インデックスのスキャンが行われる
処理に使用されるオブジェクトが表示される。
索引はなぜ速いのか
1-6 7-12
1
索引は、以下のような構造をしています。インデックスの「リーフ」の場所には実テーブルの行番号が格納されており、テーブルを一から探すよりも速くなります。
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12 リーフ
Col1 Col2
2 5
8 20
1 12
7 8
9 1
3 2
4 9
10 6
5 4
6 3
col1=2 は1 行目
なぜ索引は速いのか?
1-6 7-12
1
しかしながら、インデックスが検索条件と合わない場合は、インデックスを経由する分だけテーブルフルスキャンよりも効率が悪くなってしまいます。col1 のインデックスがあるが、 col2 を条件とした場合、強制的にインデックス読み込みにしようとすると、すべてのインデックスを確認する必要があります。
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12 リーフ
SELECT col1,col2 FROM test2WHERE col2=1;Col1 のインデック
ス
なぜ索引は速いのか?
1-6 7-12
1
テーブルの挿入をする際に、インデックスは並び替えがされます。インデックスもデータブロックごとに管理しており、新たに行挿入が発生した際にインデックス用のブロックを追加作成したり、ブロックを分割するなどの処理が発生し、インデックスなしの挿入よりパフォーマンスが落ちます。インデックスはたくさん貼っておけばよいわけではありません。
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12 リーフ
Col1 のインデックス
13
13
13
オペレーションの種類(主なもの)
Operation 処理内容
TABLE ACCESS FULL 表のすべての行を取得する
INDEX RANGE SCAN 索引から範囲をキーにして取得する
INDEX UNIQUE SCAN 索引ブロックをピンポイントで取得する
INDEX FAST FULL SCAN 索引ブロックをすべてスキャンする
NESTED LOOP ネステッドループ結合を使用した結合処理
MERGE JOIN ソートマージ結合を使用した結合処理
HASH JOIN ハッシュによる 2 つの行セットの結合
索引の種類
1-6 7-12
1
B-Tree 型
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12 リーフ
木構造になっており、データを効率よく検索できる。
索引の種類
Bitmap 型
鴻巣マラソン
リレーマラソン
皇居練習会1
皇居練習会2
1 1 1 1 1 1 1
1 1 1 1 1 1 0
1 1 0 1 0 1 1
1 1 0 0 1 1 1
H 部長 S社長 A 部員 I 部員 M 部員 H 部員 Y部員
※1:参加 0:不参加
値が2種類しかないなど、カージナリティ(値の種類)が低い場合は、Bitmap 型の 1/0 での表記のほうがパフォーマンスが良いこともある。
索引のオペレーション
1-6 7-12
1
INDEX UNIQUE SCAN : 索引ブロックをピンポイントで取得する
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12
WHERE SYAINID = 6;
索引のオペレーション
1-6 7-12
1
INDEX RANGE SCAN : 索引から範囲をキーにして取得する
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12
WHERE SYAINID BETWEEN 4 AND 6;
索引のオペレーション
1-6 7-12
1
INDEX FAST FULL SCAN : 索引ブロックをすべてスキャンする
1-3 4-6 7-9 10-12
2 3 4 5 6 7 8 9 10 11 12
WHERE SYAINID BETWEEN 1 AND 9;
結合の種類NESTED LOOP : ネステッドループ結合を使用した結合処理
SYAINCD SYAINNAME JOB MGR KONOSU_FLG
1 H PROGRAMMER 2 1
2 S PRESIDENT 1
3 A DBA 1 1
4 H SALESMAN 2 1
5 I PROGRAMMER 1 0
EMP 表
JOB SAL COMM
PRESIDENT 8000 2000
SALESMAN 5000 3000
PROGRAMMER 4000 1000
DBA 3000 1000
SAL 表
SELECT emp.syainname , sal.salFROM emp, salWHERE emp.job = sal.job;
結合の種類NESTED LOOP : ネステッドループ結合を使用した結合処理
SYAINCD SYAINNAME JOB MGR KONOSU_FLG
1 H PROGRAMMER 2 1
2 S PRESIDENT 1
3 A DBA 1 1
4 H SALESMAN 2 1
5 I PROGRAMMER 1 0
EMP 表
JOB SAL COMM
PRESIDENT 8000 2000
SALESMAN 5000 3000
PROGRAMMER 4000 1000
DBA 3000 1000
SAL 表
1)EMP 表を順に検索し、 JOB= PROGRAMMERという値を取得する
2)EMP 表を順に検索し、 JOB= PROGRAMMERという値を取得する
結合の種類MERGE JOIN : ソートマージ結合を使用した結合処理
SYAINCD SYAINNAME JOB MGR KONOSU_FLG
1 H PROGRAMMER 2 1
2 S PRESIDENT 1
3 A DBA 1 1
4 H SALESMAN 2 1
5 I PROGRAMMER 1 0
EMP 表
JOB SAL COMM
PRESIDENT 8000 2000
SALESMAN 5000 3000
PROGRAMMER 4000 1000
DBA 3000 1000
SAL 表
SELECT emp.syainname , sal.salFROM emp, salWHERE emp.job = sal.job;
結合の種類MERGE JOIN : ソートマージ結合を使用した結合処理
SYAINCD SYAINNAME JOB MGR KONOSU_FLG
3 A DBA 1 1
2 S PRESIDENT 1
1 H PROGRAMMER 2 1
5 I PROGRAMMER 1 0
4 H SALESMAN 2 1
EMP 表
JOB SAL COMM
DBA 3000 1000
PRESIDENT 8000 2000
PROGRAMMER 4000 1000
SALESMAN 5000 3000
SAL 表
1)結合条件をソートする
2)結合条件をソートする
SYAINNAME JOB SAL
A DBA 3000
S PRESIDENT 8000
H PROGRAMMER 4000
I PROGRAMMER 4000
H SALESMAN 5000
3)それぞれマージする
結合の種類HASH JOIN : ハッシュによる 2 つの行セットの結合処理
SYAINCD
SYAINNAME JOB MGR KONOSU_FLG
1 H PROGRAMMER 2 12 S PRESIDENT 13 A DBA 1 14 H SALESMAN 2 15 I PROGRAMMER 1 0
EMP 表
JOB SAL COMMPRESIDENT 8000 2000SALESMAN 5000 3000
PROGRAMMER 4000 1000DBA 3000 1000
SAL 表
SELECT emp.syainname , sal.salFROM emp, salWHERE emp.job = sal.job;
結合の種類HASH JOIN : ハッシュによる 2 つの行セットの結合処理
SYAINCD
SYAINNAME JOB MGR KONOSU_FLG
1 H PROGRAMMER 2 12 S PRESIDENT 13 A DBA 1 14 H SALESMAN 2 15 I PROGRAMMER 1 0
EMP 表
JOB SAL COMMPRESIDENT 8000 2000SALESMAN 5000 3000
PROGRAMMER 4000 1000DBA 3000 1000
SAL 表
2 )もう一つの表の結合条件式にハッシュ関数をかけて、結合できるかをハッシュテーブルで確認
SYAINID
SAL
1 40002 80003 30004 50005 4000
HASH TABLE
1)レコード数の少ない表の結合条件式をハッシュ関数にかけて、メモリ上にハッシュテーブルを作成
ハッシュ関数
ハッシュ
関数
ヒント句オペレーション( SQL を実行する際の処理方法)を固定させることができる。
Operation ヒント句 使用例
TABLE ACCESS FULL
FULL SELECT /*+ FULL(tab) */ * from tab;
INDEX RANGE SCAN INDEX SELECT /*+ INDEX(tab idx) */ * from tab;INDEX UNIQUE
SCANINDEX FAST FULL SCANNESTED LOOP USE_NL SELECT /*+ USE_NL(a b)*/ *
from a,b;MERGE JOIN USE_MERGE SELECT /*+ USE_MERGE (a
b)*/ *from a,b;
HASH JOIN USE_HASH SELECT /*+ USE_NL(a b)*/ * from a,b;
実行計画の確認方法では、実際に実行計画を確認します。
SQL> explain plan forSQL> select * from tab;
・実行計画出力 explain plan for の後に出力したい SQL を入力します。
SQL> @?/rdbms/admin/utlxpls.sql
・実行計画表示
実行計画の確認方法ただし、現在実行されている SQL の実行計画を出力したい場合は、必ずしも正しいとは限りません。この場合は、共有プール内の実行計画情報を確認します。
SQL> SELECT * FROM table (DBMS_XPLAN.DISPLAY_CURSOR(‘SQL_ID'));
DEMO
それではデモで実際に実行計画の変化を確認してみましょう!