1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLチューニングの落とし穴:インデックスが効かない意外なケース

Posted at

SQLチューニングの落とし穴:インデックスが効かない意外なケース

はじめに

SQLのパフォーマンス改善において、インデックスは非常に強力な武器です。しかし、「インデックスがあるのに遅い」という現象に遭遇したことはありませんか?

本記事では、ユーザーの入力パラメータによってインデックスの有無が実行計画に影響するケースについて解説します。


ケーススタディ:user_idでの絞り込み

例えば、動画配信サービスの視聴履歴テーブル WatchHistory に対して、特定ユーザーの視聴回数をカウントする以下のSQLを考えてみます。

SELECT COUNT(*)
FROM WatchHistory
WHERE user_id = :uid;

このSQLは、あるユーザー(user_id)がどれだけの動画を見たかを調べるものです。非常にシンプルな構文ですが、指定されるパラメータ :uid の値によって、インデックスが使われたり、フルテーブルスキャンになったりするという現象が発生します。


パターン別の実行結果

パターン user_idに対応する視聴記録件数 実行プランの傾向
一般ユーザー(例:10万件) 少ない(低選択率) インデックススキャン
ヘビーユーザー(例:1,000万件) 多い(高選択率) フルテーブルスキャン

インデックスは「絞り込み効果が高いとき」に威力を発揮します。しかし、大量の行が該当してしまう場合、インデックス経由でランダムアクセスするより、全件読み込んだ方が速いとDBMSが判断し、インデックスを使わずフルスキャンに切り替えることがあります。


問題点:入力パラメータに依存する性能変動

このような状況では、以下のような問題が起こります。

  • 同じSQL文でも、入力値によって実行時間が極端に変わる
  • テスト環境では高速でも、本番で遅くなる
  • 特定のヘビーユーザーに偏ったアクセスがあるとシステム全体が重くなる

つまり、「パラメータ次第でインデックスが無効化されるリスク」が潜んでいるのです。


対策

こうした問題に対応するには、いくつかの方法があります。

  • EXPLAINEXPLAIN ANALYZEで実行計画を確認する
  • 統計情報を適切に更新しておく(ANALYZEなど)
  • ユースケースに応じてヒント句(例:USE INDEX)を使う
  • ヘビーユーザーのデータを別テーブルやパーティションに分割する
  • マテリアライズドビューやキャッシュの活用

まとめ

インデックスは万能ではありません。同じクエリでも、ユーザーが入力するパラメータによって実行計画が大きく変わることがあります。とくに、選択率が高い値が入力された場合、インデックスが無視され、フルスキャンになることがある点には注意が必要です。

SQLチューニングでは、「実際にどの値が使われるか?」を意識して、現実的なケースでの実行計画をチェックすることが重要です。


参考

  • 書籍:『達人に学ぶ SQL徹底指南書』(ミック著)
1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?