本稿では、現場業務で使用しているデータベースから、SQL のパフォーマンスが劣化した際に心得ておきたい事項を記載しています。
本稿では、Oracle Database 11g Release 2 を対象としています。
Oracle Database において、初回の SQL 実行時に最適な実行計画が生成されます。しかし、時として実行した SQL が遅くなるといった事例は少なくありません。
そのため、最終的には人の手でチューニングを行うことにより、応答速度が高速に改善されたり、パフォーマンスの劣化を未然に防ぐことにつながります。
SQL が遅くなる原因は多岐に渡りますが、まず出来ることとしての確認ポイントを列挙します。
表結合は非常に負荷が高い処理であるため、適切な結合方法が実行計画で選択されているかを確認する。
主な結合方法は、ネステッドループ結合、ソートマージ結合、ハッシュ結合とありますが、一般的にオンライン処理のような数件の結果表示が求めらるようなケースでは、ネステッドループ結合、バッチ処理等で大量の結果を返す SQL はハッシュ結合を用いることが適しています。
ハッシュ結合やソート処理は大量の PGA メモリが消費されます。メモリが足りないときは、ディスクの一時表領域を使用してしまうため、パフォーマンスの劣化を招きます。SQL の待機イベントで一時表領域へのアクセスが見られるときは、PGA メモリを拡張するか、あるいは結合方法をネステッドループ結合に変更する等の検討をしてください。
索引を使用することで効率的に検索することができます。WHERE 句に指定される絞り込み条件により全体レコードの 10%以下が返される列に索引を付与することで、パフォーマンスの向上が図れます。
WHERE 句の記述で、TO_CHAR などの関数を利用したり、LIKE で中間一致や後方一致を利用している場合、IS NULL や NOT IN 句で比較されている場合等は、索引が有効に活用されていません。代替えが出来ないか検討をしてください。
以下のようなケースでは、索引が利用されない。
select 名前, クラス, 誕生日
from 生徒
where to_char(birth_day, 'YYYY/MM/DD') = '2025/03/27'
対処方法としては、以下のように変更することで、索引が利用可能となる。
select 名前, クラス, 誕生日
from 生徒
where birth_day = to_date('2025/03/27', 'YYYY/MM/DD')
索引は表と同時に更新されるため、断片化が進み、少しずつ性能が劣化していきます。もし索引が作成されてから長期間経過している場合は、再構築をすることで性能改善が図れることがあります。
索引構造情報を確認する。
ANALYZE INDEX <索引名> VALIDATE STRUCTURE
select HEIGHT, LF_ROWS, DEL_LF_ROWS, PCT_USED
from INDEX_STATS
主な確認項目としては、以下に示します。
列名 | 説明 | 確認内容 |
---|---|---|
HEIGHT | Bツリーの高さ | 階層の高さが 4 階層以上であれば、再構築を検討 |
LF_ROWS | リーフ行の数(索引内の値) | 削除された行エントリーの占める割合が 20~30%を超える場合(DEL_LF_ROW/LF_ROWS > 0.2)、再構築を検討 |
DEL_LF_ROWS | 索引内の削除されたリーフ行の数 | |
PCT_USED | Bツリー内で割り当てられた領域に対する、使用されている領域の割合 | 領域の使用割合が低下した場合、再構築を検討 |
参照URL:https://www.oracle.com/jp/a/tech/docs/technical-resources/performance-tuning.pdf
最後まで、お読みいただきありがとうございます。
SQL が遅くなる原因は上記以外にも存在しますが、まず確認したいポイントとして列挙しました。
私自身、この様なポイントを日頃から意識し、業務の効率化を図れるよう邁進しています。