「遅い SQL をチューニングしたいが、どこから手をつければよいかわからない」という場面で活躍するのがSQL Tuning Advisor(SQL チューニングアドバイザ)です。Oracle が SQL を自動解析し、統計情報の収集不足・インデックスの欠如・プラン非効率などを検出して推奨事項を提示します。
SQL Tuning Advisor は DBMS_SQLTUNE パッケージから PL/SQL で呼び出せるほか、Oracle Enterprise Manager(OEM)や SQL Developer からも利用できます。
この記事でわかること
- SQL Tuning Advisor の仕組みと推奨事項の種類
- DBMS_SQLTUNE.CREATE_TUNING_TASK で sql_id を指定してタスクを作成する
- EXECUTE_TUNING_TASK・REPORT_TUNING_TASK で解析結果を取得する
- ACCEPT_SQL_PROFILE で SQL プロファイルを適用する(実行計画を改善する)
- SQL チューニングセット(STS)で AWR からの複数 SQL を一括解析する
- タスクの管理(一覧確認・削除)方法
ライセンス要件
SQL Tuning Advisor は Oracle Diagnostics Pack と Oracle Tuning Pack のライセンスが必要です。本番環境で使用する場合は事前にライセンスを確認してください。
SQL Tuning Advisor は Oracle Diagnostics Pack と Oracle Tuning Pack のライセンスが必要です。本番環境で使用する場合は事前にライセンスを確認してください。
SQL Tuning Advisor が提示する推奨事項の種類
| 推奨種別 | 内容 |
|---|---|
| Statistics Analysis | 統計情報が古い・欠如している場合に再収集を推奨する |
| SQL Profile | より良い実行計画に誘導するためのプロファイルを作成する(ヒント不要) |
| Access Path Analysis | フルスキャンを減らすためのインデックス追加を推奨する |
| SQL Structure Analysis | SQL の書き換えを推奨する(アンチジョインや EXISTS の活用など) |
| Alternative Plan | AWR・SQL Plan Baseline に保存された過去の優良プランを代替案として提示する |
sql_id を指定して解析タスクを作成・実行する
カーソルキャッシュから遅い SQL の sql_id を特定する
-- 実行時間が長い SQL の sql_id を特定する
SELECT sql_id, plan_hash_value,
ROUND(elapsed_time / executions / 1000) AS avg_elapsed_ms,
executions,
SUBSTR(sql_text, 1, 80) AS sql_text_head
FROM V$SQLAREA
WHERE executions > 0
AND elapsed_time / executions > 1000000 -- 平均 1 秒超の SQL
ORDER BY elapsed_time / executions DESC
FETCH FIRST 10 ROWS ONLY;
sql_id を指定してタスクを作成・実行・レポートを取得する
DECLARE
v_task_name VARCHAR2(30) := 'TUNING_TASK_' || TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS');
v_report CLOB;
BEGIN
-- ① チューニングタスクを作成する
v_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
sql_id => 'abc123def456g', -- V$SQLAREA で確認した sql_id
plan_hash_value => NULL, -- NULL = すべてのプランを対象
scope => 'COMPREHENSIVE', -- COMPREHENSIVE(完全解析)/ LIMITED(軽量)
time_limit => 60, -- 解析の最大実行時間(秒)
task_name => v_task_name,
description => '遅いクエリの解析'
);
DBMS_OUTPUT.PUT_LINE('タスク名: ' || v_task_name);
-- ② タスクを実行する
DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => v_task_name);
-- ③ レポートを取得する
v_report := DBMS_SQLTUNE.REPORT_TUNING_TASK(
task_name => v_task_name,
type => 'TEXT', -- TEXT / HTML / XML
level => 'TYPICAL' -- TYPICAL / BASIC / ALL(詳細度)
);
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_report, 1, 32767));
END;
/
チューニングタスクの一覧確認と管理
タスクの状態と推奨事項を確認する
-- 実行済みタスクの一覧を確認する
SELECT task_name, status, created, last_modified, description
FROM DBA_ADVISOR_TASKS
WHERE advisor_name = 'SQL Tuning Advisor'
ORDER BY created DESC;
-- 推奨事項を確認する(DBA_ADVISOR_FINDINGS / DBA_ADVISOR_RECOMMENDATIONS)
SELECT
f.task_name,
f.finding_id,
f.type, -- STATISTICS(統計)/ SQL PROFILE / INDEX / RESTRUCTURE SQL など
f.message, -- 推奨事項の内容
r.benefit, -- 推定改善率(%)
r.rec_id
FROM DBA_ADVISOR_FINDINGS f
JOIN DBA_ADVISOR_RECOMMENDATIONS r
ON f.task_id = r.task_id AND f.finding_id = r.finding_id
WHERE f.task_name = 'YOUR_TASK_NAME'
ORDER BY r.benefit DESC;
タスクを削除する
-- 不要になったタスクを削除する
BEGIN
DBMS_SQLTUNE.DROP_TUNING_TASK(task_name => 'YOUR_TASK_NAME');
END;
/
SQL プロファイルを適用して実行計画を改善する
SQL Tuning Advisor がプロファイルを推奨した場合、ACCEPT_SQL_PROFILE で適用できます。SQL プロファイルはヒント句をソースコードに追加せずに実行計画を誘導できます。
推奨 SQL プロファイルを適用する
-- レポートで推奨された SQL プロファイルを適用する
DECLARE
v_profile_name VARCHAR2(50);
BEGIN
v_profile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE(
task_name => 'YOUR_TASK_NAME',
task_owner => 'SYS', -- タスクの所有者
name => 'PROFILE_SLOW_Q1', -- プロファイル名(省略可)
force_match => FALSE, -- TRUE = バインド変数の値に関係なく適用
replace => TRUE -- TRUE = 同名プロファイルを上書き
);
DBMS_OUTPUT.PUT_LINE('適用されたプロファイル名: ' || v_profile_name);
END;
/
-- 適用されたプロファイルを確認する
SELECT name, category, status, sql_text
FROM DBA_SQL_PROFILES
ORDER BY last_modified DESC;
-- プロファイルを無効化する(取り消しではなく一時停止)
BEGIN
DBMS_SQLTUNE.ALTER_SQL_PROFILE(
name => 'PROFILE_SLOW_Q1',
attribute_name => 'STATUS',
value => 'DISABLED' -- 再有効化は 'ENABLED'
);
END;
/
-- プロファイルを削除する
BEGIN
DBMS_SQLTUNE.DROP_SQL_PROFILE(name => 'PROFILE_SLOW_Q1');
END;
/
SQL チューニングセット(STS)で複数 SQL を一括解析する
SQL チューニングセット(STS: SQL Tuning Set)は複数の SQL をまとめて管理・解析するコンテナです。AWR の履歴から問題 SQL を抽出してまとめてチューニングアドバイザにかけるワークフローで使います。
AWR の SQL 履歴から STS を作成して Tuning Advisor にかける
-- ① STS を作成する
BEGIN
DBMS_SQLTUNE.CREATE_SQLSET(
sqlset_name => 'STS_SLOW_SQLS',
description => '過去24時間の遅い SQL 集合'
);
END;
/
-- ② AWR から STS に SQL を追加する(過去 24 時間・実行時間 1 秒超)
DECLARE
v_cursor DBMS_SQLTUNE.SQLSET_CURSOR;
BEGIN
-- AWR の 2 スナップショット間の SQL を取得するカーソルを作成する
OPEN v_cursor FOR
SELECT VALUE(p) FROM TABLE(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(
begin_snap => (SELECT MAX(snap_id) - 24 FROM DBA_HIST_SNAPSHOT), -- 24 スナップ前
end_snap => (SELECT MAX(snap_id) FROM DBA_HIST_SNAPSHOT), -- 最新スナップ
basic_filter => 'elapsed_time > 1000000', -- 1 秒超
ranking_measure1 => 'elapsed_time',
result_limit => 50 -- 上位 50 SQL
)
) p;
-- STS に追加する
DBMS_SQLTUNE.LOAD_SQLSET(
sqlset_name => 'STS_SLOW_SQLS',
populate_cursor => v_cursor
);
CLOSE v_cursor;
END;
/
-- ③ STS 全体にチューニングタスクをかける
DECLARE
v_task VARCHAR2(50);
BEGIN
v_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(
sqlset_name => 'STS_SLOW_SQLS',
scope => 'COMPREHENSIVE',
time_limit => 300,
task_name => 'STS_TUNING_TASK'
);
DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'STS_TUNING_TASK');
END;
/
-- ④ レポートを出力する
SET LONG 100000
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('STS_TUNING_TASK') FROM DUAL;
-- ⑤ STS を削除する(不要になったら)
BEGIN
DBMS_SQLTUNE.DROP_SQLSET(sqlset_name => 'STS_SLOW_SQLS');
END;
/
まとめ
- CREATE_TUNING_TASK → EXECUTE_TUNING_TASK → REPORT_TUNING_TASK の3ステップで推奨事項を取得する
- SQL プロファイルは ACCEPT_SQL_PROFILE で適用。ソースコード変更なしで実行計画を改善できる
- SCOPE=COMPREHENSIVE は完全解析。制限時間(time_limit)内に収まるよう設定する
- STS(SQL チューニングセット)で AWR の問題 SQL を一括取得・解析するワークフローが実用的
- Diagnostics Pack と Tuning Pack のライセンスが必要な点に注意する
AWR スナップショットの取得と分析は AWR・ASH完全ガイドを参照してください。実行計画の詳細確認は DBMS_XPLAN完全ガイドを参照してください。SQL プロファイルとプランの固定化を比較したい場合は SQL Plan Management(SPM)完全ガイドも参照してください。