50%の割合で条件にヒットすると予測を立てて実行計画を算出します
1. DEPT 表をフルスキャンする 2. EMP 表をフルスキャンする
3. 2 の結果セットをソートする 4. 2 と 4 の結果をマージ
• 実行計画例:
表結合 方法
ネステッドループ結合 ハッシュ結合 ソートマージ結合
直積結合
実行計画を判断するポイント
表結合方法
索引を利用して 参照 表を直接参照
データ アクセス方法
全表スキャン
(TABLE ACCESS FULL)
索引のレンジスキャン
(INDEX RANCE SCAN)
索引の一意スキャン
(INDEX UNIQUE SCAN)
索引のフルスキャン
(INDEX FULL SCAN)
索引の高速フルスキャン
(INDEX FAST FULL SCAN)
ネステッドループ結合
索引のスキップスキャン
(INDEX SKIP SCAN)
ハッシュ結合 ソートマージ結合
直積結合
判断のポイント 分岐の種類
<Insert Picture Here>
まとめ
• それぞれの特性と考慮点から「検討」「検証」「判断」すること
•
適切な索引が作成されているか?•
最適な索引が使用されているか?• WHERE
句条件が適切か(コーディング、条件指定)?•
表のフルスキャンの方が効率的か(索引を使用しても10%以上の表データアクセスなど)?•
ネステッドループ結合で内部表のフルスキャンが発生していないか?•
カーディナリティの小さい表から結合されているか?最適化のアプローチ
SQL によるデータの取得を最小のブロックアクセスで行うことが原則です。
しかしながら、 SQL 単体を最適化(レスポンス改善)するアプローチだけ では不十分です。
SQL 単体の最適化
• 実行計画の違いによる必要リソース( CPU, メモリなど)のバランスで判断
• サーバ上でOracle以外のアプリケーションが動作し物理メモリが圧迫されている
→ ハッシュ結合やソートマージ結合が同時に実行されて物理メモリが圧迫されないか
• CPU使用率が高い
→無駄なソート処理がないか、ネステッドループ結合によりCPU負荷が高くなっていないか
最適化のアプローチ
SQL パフォーマンス問題を解決するには
SQL 単体の最適化だけではなく、システム全体の最適化をふまえて 判断することが重要である
システム全体の最適化
<Insert Picture Here>
Appendix
表結合順序
現状を分析する手順
① 表の結合関係をクリアにする
• SQL 文、索引定義情報、統計情報
• WHERE 句に含まれている列
• 結合されている列同士の結合関係
• 推移律
• 選択率とカーディナリティ
② 結合順序のスタートポイントを見つける
• どれくらい絞れるか
• 絞り込める表(スタートポイント)はどれか
[SQL文]
SELECT count(*) FROM tab1 t1
, tab2 t2 , tab3 t3 , tab4 t4 , tab5 t5 WHERE t1.id = t2.id
AND t1.id = t3.id AND t2.class = t5.class AND t3.class = t4.class AND t4.flag = 'Y'
AND t5.num = TO_NUMBER(:b1) AND t4.code = TO_NUMBER(:b2)
AND t1.start_date <= (TO_DATE(:b3, 'yyyymmdd') + 1) AND t1.end_date > TO_DATE(:b3, 'yyyymmdd')
[索引の定義]
TABLE_NAME INDEX_NAME COLUMN_NAME KIND
--- --- --- ---TAB1 ---TAB1_P1 ID Primary Key
TAB1_U1 ID, END_DATE Unique Key TAB2 TAB2_PK ID, CLASS, ZONE Primary Key
TAB2_I1 CLASS, ID TAB2_I2 ID
TAB3 TAB3_P1 ID, CLASS, DEPTH Primary Key TAB3_I1 CLASS, ID
TAB4 TAB4_PK CODE Primary Key TAB4_I1 CLASS, CODE
TAB5 TAB5_PK CLASS Primary Key TAB5_U1 DATA, CLASS, NUM Unique Key TAB5_I1 NUM, DATA
• SQL 文、索引定義情報
表結合順序
①表の結合関係をクリアにする
• 統計情報
[SQL文]
SELECT count(*) FROM tab1 t1
, tab2 t2 , tab3 t3 , tab4 t4 , tab5 t5 WHERE t1.id = t2.id
AND t1.id = t3.id AND t2.class = t5.class AND t3.class = t4.class AND t4.flag = 'Y'
AND t5.num = TO_NUMBER(:b1) AND t4.code = TO_NUMBER(:b2)
AND t1.start_date <= (TO_DATE(:b3, 'yyyymmdd') + 1) AND t1.end_date > TO_DATE(:b3, 'yyyymmdd')
[表の統計情報]
OWNER TABLE_NAME COLUMN_NAME NUM_ROWS NUM_DISTINCT --- --- --- ---SCOTT TAB1 ID 275 275 SCOTT TAB1 START_DATE 275 5 SCOTT TAB1 END_DATE 275 1 SCOTT TAB2 ID 282 273 SCOTT TAB2 CLASS 282 17 SCOTT TAB3 ID 17442 274 SCOTT TAB3 CLASS 17442 8210 SCOTT TAB4 CODE 834030 834030 SCOTT TAB4 FLAG 834030 1 SCOTT TAB4 CLASS 834030 834030 SCOTT TAB5 NUM 133 132 SCOTT TAB5 CLASS 133 133