0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

データ特性・検索ユースケースに合わせたインデックス選定

Last updated at Posted at 2025-06-08

データ特性・検索ユースケースに合わせたインデックス選定

  • インデックス選定の際、データ特性・ユースケースから、逆引きで、最適なものを選定できるよう体系的に整理した

ユースケース別インデックス選定表

検索ユースケース データ特性 推奨インデックス
一意なキーによる検索 主キーでの検索 主キーインデックス
非ユニークなキーの検索 主キー以外で検索を行う機会のあるデータ セカンダリインデックス
JOIN(多対一、多対多) 使用上、関連テーブルとの結合が必要なデータ セカンダリインデックス
複数カラムを使った検索やユニーク制約 使用上、複数カラムの組合せを行う場合がある(性・名など) 連結インデックス
範囲検索やソート ソート順、連続性のある値(履歴・時系列データ) クラスタインデックス
多次元検索 多次元な要素でかつ、範囲検索をするデータ(緯度 x 経度・時間 x 金額など) 多次元インデックス
クエリの全カラムがインデックスに含まれる 列数の少ないデータの閲覧・書き込みがあまりないデータ(インデックスの更新に負荷がかからないもの) カバリングインデックス

主キーインデックス

  • 主キーに張られるインデックス
  • 一意性を保証し、最も高速な検索ができる

用途

  • 主キーによる検索
  • 主キー制約の一意性検証
  • 結合先(1側)のレコード参照
SELECT * FROM users WHERE id = 1;

-- orders.user_idそれぞれに対し、一回のアクセスで、結合用のユーザーレコードを取得できる
SELECT * FROM orders
JOIN users ON orders.user_id = users.id;

補足


セカンダリインデックス

  • 主キー以外のキーに手動で追加できるインデックス
  • WHERE句やJOIN、ソート、グルーピングなど、さまざまな用途に効果がある

用途

  • 非ユニークなカラムの検索
  • JOIN のパフォーマンス向上
  • WHERE句、GROUP BY、ORDER BY の高速化
SELECT * FROM users WHERE name = '太郎';

SELECT users.name, orders.order_date
FROM users
JOIN orders ON users.id = orders.user_id
WHERE orders.order_date >= '2025-01-01';

特に効果的なケース

  • 多対一・多対多のリレーション

  • フィルタ条件が特定のカラムに集中している場合に有効


連結インデックス(複合インデックス)

  • 複数のカラムを1つのインデックスとして結合し、検索や制約に利用する

用途

  • 複数カラムの組み合わせによる検索
  • 複数カラムによるユニーク制約の検証
-- email + passwordの組み合わせにユニーク制約をかける
CREATE UNIQUE INDEX idx_user_email_password
  ON users(email, encrypted_password);

INSERT INTO users (email, encrypted_password)
VALUES ('a@example.com', 'xxx');

注意点

  • 左端一致の原則に注意:インデックスの先頭カラムから順に使わないと効果が薄れる

多次元インデックス

  • R-treeなどの構造を用いた、空間情報(位置・領域)に特化したインデックス

用途

  • 複数カラムの範囲にまたがる検索(例:緯度・経度)
SELECT * FROM restaurants
WHERE latitude BETWEEN 35.0 AND 36.0
  AND longitude BETWEEN 139.0 AND 140.0;

補足

  • 空間検索やベクトル検索に強い
  • GISエンジン、MongoDB、Elasticsearchなどでも利用される

クラスタインデックスとは

  • インデックス順に物理データが並んで格納される構造
    • インデックスがそのままデータの実態を持っている
  • MySQL InnoDBでは主キーインデックスがクラスタインデックスになる

用途

  • 範囲検索(日時、連番IDなど)
  • ORDER BY の高速化
SELECT * FROM logs
WHERE created_at BETWEEN '2025-01-01' AND '2025-01-31';

特徴

  • テーブルに1つしか持てない
  • インデックスの順番でデータが格納されるため、範囲取得が非常に速い

カバリングインデックス

  • クエリに必要なすべてのカラムをインデックスがカバー状態
    • インデックスとしては、本質的にセカンダリインデックスと同じ
  • 実データを読み込む必要がないため、非常に高速

用途

  • クエリで使用するカラムをすべてインデックスに含める
-- emailとcreated_atの両方に対するクエリ
CREATE INDEX idx_user_email_created
  ON users(email, created_at);

SELECT email, created_at
FROM users
WHERE email = 'user@example.com';

効果

  • ディスクI/O削減
  • テーブルアクセスなしでクエリを完結できる(Covering)

まとめ

インデックス種別 説明
主キーインデックス 主キーに自動的に張られ、一意性と高速アクセスを保証する
セカンダリインデックス 任意のカラムに追加でき、検索・JOIN・ソートを効率化する
連結インデックス 複数カラムをまとめたインデックス。順序に注意しながら検索・制約に使える
多次元インデックス 緯度経度など多軸の範囲検索に適した構造。空間検索に強い
クラスタインデックス インデックス順に物理データを格納。範囲検索やORDER BYに最適
カバリングインデックス クエリが必要とする全カラムがインデックスに含まれている状態。高速でI/O削減
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?