「重いSQL」と一口に言っても、Elapsed Timeが長いのかGetsが多いのか、原因はSQLごとに違います。ランキングの使い分けを誤って的外れなチューニングをしてしまった反省から書いています。

SQL Statistics の全体像

チューニング対象SQL特定図

図1: SQLチューニング対象の特定手順

AWRの SQL Statistics セクションには、複数の観点でSQLをランキングしたテーブルがあります。 それぞれ異なる問題を炙り出すため、目的に合わせて使い分けます。

テーブル名ランキング基準適した問題
SQL ordered by Elapsed Time合計経過時間全体的に最も重いSQL(最重要)
SQL ordered by CPU Time合計CPU消費時間CPU高負荷の原因SQL
SQL ordered by Gets論理読み込みブロック数バッファキャッシュを大量消費するSQL
SQL ordered by Reads物理読み込みブロック数I/Oを引き起こすSQL
SQL ordered by Executions実行回数頻繁に呼ばれる軽いSQL(積み重ね)
SQL ordered by Parse Callsパース回数バインド変数未使用SQL

SQLの基礎は PART 05 — SQL Statistics 重いSQLの特定(AWR入門) を、項目定義は PART 05 — SQL Statistics 詳細(定義書) を参照。

Elapsed Time で重いSQLを特定する

まず SQL ordered by Elapsed Time を見ます。 Elapsed Time(s)(合計実行時間)が上位のSQLが全体の負荷に最も寄与しています。

列名意味注目ポイント
Elapsed Time (s)合計経過時間(秒)最も総合的な重さを示す
Executions実行回数高回数 × 軽い1回 or 低回数 × 重い1回を区別
Elapsed Time / Execute1回あたりの経過時間1回が重いSQLを特定できる
% Total DB TimeDB Timeに占める割合30%超のSQLは最優先でチューニング

CPU / Gets / Reads から原因を分析する

Elapsed Timeが高いSQLが特定できたら、その原因を CPU Time / Gets / Reads の比率で診断します。

状況原因の仮説次のアクション
CPU Time ≒ Elapsed TimeCPU使用が多い(ソート・ハッシュ結合・フルスキャン)実行計画を確認、インデックス追加を検討
Reads が多い(Getsも多い)物理I/O + バッファキャッシュミスPART 06 I/O分析
Gets が多い(Readsは少ない)論理読み込みが多い(効率の悪いインデックスorフルスキャン)実行計画の見直し
Elapsed ≫ CPU(待機が多い)I/O待ち or 競合待ちPART 04 Wait分析

SQLチューニングよくある失敗パターン

SQL Statisticsで対象SQLを特定した後、チューニングで陥りやすい誤りと正しいアプローチを整理する。

失敗パターンなぜ問題か正しいアプローチ
Elapsed Timeだけ見てインデックスを追加する Gets(論理読み込み)が多い場合はインデックスが役立つが、Readsが多い場合はストレージ性能の問題かもしれない CPU/Gets/Readsの比率で原因を切り分けてから対処を決める
実行計画を見ずにSQLを書き直す 書き直し後に別の非効率が生まれる。フルスキャンが意図的な場合もある DBMS_XPLANで現在の実行計画を確認し、どのオペレーションがコストを占めるかを把握してから修正
統計情報の更新を忘れる Optimizerが古い統計を使うと全件スキャンを選択することがある。インデックス追加だけでは解消しない DBMS_STATSで対象テーブルの統計情報を更新し、実行計画が変わることを確認
Parse Callsが多いのを見逃す Executions ≒ Parse Callsならバインド変数未使用。共有プール競合が常態化している アプリ側でバインド変数を使うよう修正。CURSOR_SHARINGは応急処置

SQL_ID から実行計画へのドリルダウン

AWRレポート(HTML形式)では SQL_ID がリンクになっており、クリックするとSQL全文と実行計画(ある場合)に飛べます。 また、以下のSQLでV$SQL_PLANから実行計画を取得することも可能です。

⚠️ 実行計画の確認

AWRのSQL Statisticsはスナップショット期間中の累積値です。問題発生時点の実行計画は DBA_HIST_SQL_PLANAWR SQL Report で確認してください。実行計画の読み方は 実行計画セクション定義書 を参照。

優先順位付けの考え方

SQLチューニングの優先順位

% Total DB Time が高いSQL(全体負荷への寄与が大きい)
Elapsed / Execute が異常に高いSQL(1回が重い)
Parse Calls ≒ Executions のSQL(毎回ハードパース)
④ 実行回数が多く積み重なっているSQL