お疲れ様です。
はるさらと申します。
今回はOracleのSQLの速度改善や
チューニングの方法について記載していきます。
システム開発の現場でOracleを使っていると、
ふとこんな場面に出くわすことがあります。
「なんか画面がやたら重い……?」
「SQLが原因で処理が遅いかも?」
SQLはちょっとした書き方や設計の違いだけで
パフォーマンスが大きく変わってしまうんです。
単体環境では問題なく動いていたけど
結合、総合テストで環境が変わって
データ量が増えたら途端に処理が重くなってしまった話は
システム開発でよく聞く困りごとの1つです。
この記事では、Oracle SQLの基本的な
パフォーマンスチューニングを紹介していきますので
意識して製造することでプロジェクトの成功に役立ててください!
SQLの速度改善のため見直すべきポイント
ここからはSQLの速度遅延に
繋がってしまうポイントをいくつか紹介していきます。
今作成しているSQLに当てはまってしまう点はないか
順次確認していくことで、
速度改善につながっていく内容ですので
是非、目を通していってください。
SELECT * は使わない!
まず最初にチェックしたいのがこれ。
SELECT * FROM users;
こういった「SELECT *」は便利に見えますが、
実はパフォーマンス的にはNGな書き方です。
なぜ良くないの?
- 不要なカラムまで全部取得してしまう
- ネットワークに無駄なデータを流す
- Oracleの実行計画が最適にならない場合もある
結果、表示が遅くなる要因になります。
— 良い例
SELECT user_id, user_name FROM users;
また、ビューを使うときも SELECT *
していると、
基のテーブル構成変更で不具合が起こることがあるため、
使うカラムだけを明示するように心がけましょう。
WHERE句でインデックスを活かす
Oracleでは、**インデックス(索引)**が効くかどうかで
SQLの速度が大きく変わります。
よくあるNG例がこちら:
— インデックスが効かないパターン
WHERE TO_CHAR(created_at, ‘YYYY-MM’) = ‘2025-05’
こうして関数を使ってしまうと、インデックスが無効になります。
代わりに、範囲指定で書くのが基本です。
— インデックスが効く書き方
WHERE created_at >= TO_DATE(‘2025-05-01’, ‘YYYY-MM-DD’)
AND created_at < TO_DATE(‘2025-06-01’, ‘YYYY-MM-DD’)
インデックスが効かない他の例
WHERE NVL(column_name, 'X') = 'Y'
→ 関数でカラムを囲うと基本NG。
LIKE句使用時の注意
WHERE name LIKE '%田中%'
→ 先頭にワイルドカード(%
)があるとインデックスが効かない。
暗黙的な型変換の罠
WHERE user_id = '123' -- 数値型に文字列
→ カラム型とリテラルの型が合っていないとインデックスが使われない。
JOIN条件の書き忘れに注意
テーブルを結合する時は、JOIN条件をしっかり書くことが超重要です。
条件が足りないと、**大量の組み合わせ(大きな中間結果)**ができてしまい、
SQLが終わらないくらい重くなることもあります。
— NG:条件が足りない
SELECT *
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
— OK:必要な条件をすべて指定
SELECT *
FROM orders o
JOIN customers c
ON o.customer_id = c.customer_id
AND o.store_id = c.store_id;
**「件数が想定より多くなってないか?」**も必ずチェック!
サブクエリはネストしすぎない
サブクエリを多用しすぎると、SQLが複雑になり、
可読性もパフォーマンスも悪くなりがちです。
— NG例:ネストが深すぎて見づらい
SELECT *
FROM (
SELECT *
FROM (
SELECT …
FROM …
)
)
こういった場合は、**WITH句(共通表式)**を使ってスッキリ書きましょう。
— OK例:読みやすくなる
WITH recent_orders AS (
SELECT * FROM orders WHERE created_at > SYSDATE – 30
)
SELECT * FROM recent_orders;
SQLも“整理整頓”が大切です。
なぜWITH句が有効か?
- SQLエンジンが最適化しやすくなる
- 複数箇所で同じサブクエリを再利用できる
統計情報は定期的に更新しよう
Oracleは、SQLを最適に処理するために「統計情報」を使います。
でも、この情報が古くなると、**実行計画(処理の手順)**がズレてしまい、
逆に遅くなることがあります。
テーブルに大量のデータ追加・削除があった後などは、
統計情報を手動または自動で更新しておくと安心です。
— テーブル単体で更新
EXEC DBMS_STATS.GATHER_TABLE_STATS(‘SCHEMA_NAME’, ‘TABLE_NAME’);
— スキーマ全体を更新
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(‘SCHEMA_NAME’);
更新タイミングの目安
- 10%以上のデータが増減したら更新を検討。
用語がわからなくても大丈夫!チューニング初心者向けミニ用語集
「インデックス? 統計情報? よく聞くけど難しそう…」という方のために、
用語をざっくり解説します。
インデックス
データベースの「索引(さくいん)」のようなもの。
検索や絞り込みが速くなる。
📘 例:本の「索引」を使えば、目的のページにすぐ飛べるのと同じイメージ。
統計情報(Statistics)
OracleがSQLの処理順を決めるときの「参考データ」。
- テーブルに何行あるか
- カラムの値のばらつきはどうか
などの情報が含まれていて、これを元に実行計画を選ぶ。
実行計画(Execution Plan)
OracleがSQLをどう処理するかの「手順表」。
「どのテーブルから先に読んで、どの方法で結合するか?」などを決める。
ツールやコマンド(EXPLAIN PLAN
)を使うと確認できる。
フルスキャン(全表スキャン)
インデックスを使わず、テーブル全体を頭から最後まで読む処理方法。
行数が多いと大幅に遅くなるためNG!!
まとめ:SQLの速度問題は小さな意識で大きく変わる
チェックポイント | 理由 |
---|---|
SELECT * を避ける | 不要なデータ取得を防ぐ |
WHERE句の書き方に注意 | インデックスが効かなくなることがある |
JOIN条件を漏らさない | データ量が爆増して重くなる原因に |
サブクエリを整理する | 読みやすく、処理も速くなる |
統計情報を更新する | Oracleが正しい判断をするために必要 |
SQLのチューニングって、最初はとっつきにくいかもしれません。
でも、ちょっとした書き方や考え方で、大きく改善できるのも事実です。
「画面が遅いな…」と感じたら、
今回ご紹介したポイントを1つずつ見直してみてくださいね。
どなたかのお役に立てば幸いです。
それではまたー!