コンテンツにスキップ

データベースのインデックス戦略が適切で、クエリの最適化がされているか?

Type: DeepDive
Category: パフォーマンス・スケーラビリティ
Audience: 設計リーダー / SRE / インフラ設計者 / レビュー担当者


背景・概要

大量データを扱うシステムではインデックス設計が検索・更新パフォーマンスに直結する

特に読み取り頻度の高いAPIでは、適切なカバリングインデックスや結合キーの最適化が不可欠

最適化されていないクエリは本番環境で急激なレイテンシ悪化・DB負荷増につながりやすく、ボトルネックになり得る


  • created_at や tenant_id による時系列/テナント別取得が多いため、複合インデックス (tenant_id, created_at) を設定する
  • GINインデックスを利用して、JSONB型のタグ検索を高速化する
  • 利用頻度の高いSELECT文に対して、インデックスがカバリングとなるよう必要カラムを調整(例:SELECT id, status, created_at WHERE tenant_id = ... → インデックスに含める)

よくある失敗例

  • フィルターに使用するカラム(例:deleted_at IS NULL)にインデックスがなく、毎回フルテーブルスキャンが発生
  • 結合クエリでJOIN先のキーにインデックスが貼られておらず、Nested Loop Joinになって想定外の遅延が生じる
  • 高速化のためにインデックスを貼りすぎて、INSERT/UPDATEパフォーマンスが悪化
  • カバリングインデックスを意識せず、毎回テーブルアクセスが発生してI/Oが無駄に多くなる

FAQ

Q. 使用頻度が高いカラムには全部インデックスを貼るべき?

A. いいえ、インデックスは読み取りを高速化するが、更新コストとストレージを増やすためクエリ頻度・用途を見てバランスを取るべき

Q. 結合クエリでインデックスを貼るべき対象は?

A. 結合キー(JOIN ON の左右どちらも)と、WHERE句・ORDER句で使われるカラムは候補になる

Q. カバリングインデックスとは?

A. クエリに必要なすべてのカラムがインデックスに含まれていて、テーブル本体にアクセスせずに済む状態。なおテーブルスペースとのトレードオフであることに気をつけられたい


関連観点