MySQL のインデックス

最終更新: 2022-06-16 20:46:43 +0800 +0800
原文は英語で書かれています。あなたはAI翻訳版を読んでいます。

InnoDB は主インデックスとセカンダリインデックスを B+ 木で実装します。インデックスの順序が選択性の高い述語、結合、範囲スキャン、または順序付け要件と一致すると I/O を削減できますが、インデックス付きのすべての行に対する書き込み処理とストレージが増加します。

クラスター化インデックスとセカンダリインデックス #

InnoDB テーブルは行データをクラスター化インデックスに格納します。InnoDB は宣言された主キーを選択し、そうでなければ最初の適切な非 NULL 一意キーを選択し、どちらもなければ内部の隠しキーを作成します。各セカンダリインデックスエントリには主キー値が格納されるため、短く安定した主キーを宣言してください。

セカンダリインデックスには、インデックス対象の列と主キー値が格納されます。クエリがセカンダリインデックスにない列を必要とする場合、一致する各エントリについてクラスター化インデックスのルックアップが実行されます。測定されたコストを削減できる場合にのみカバリングインデックスを追加してください。幅の広いインデックスはページのファンアウトを減らし、書き込みオーバーヘッドを増加させます。

複合インデックス #

(tenant_id, created_at, id) では、B+ 木は次を効率的に検索できます。

sql
WHERE tenant_id = ? AND created_at >= ?
ORDER BY created_at, id

ツリーの順序は tenant_id から始まるため、created_at だけから効率的にシークすることはできません。一般的な設計では、等値述語を範囲述語より前に置き、その後に順序付けまたはカバレッジを満たすために必要な列を置きます。実際の述語、データ分布、結果サイズによってインデックス順序は変わるため、EXPLAIN ANALYZE で選択を検証してください。

インデックスの種類と診断 #

UNIQUE は不変条件を適用すると同時にアクセスパスを作成します。InnoDB のインデックスの大半は B ツリーです。FULLTEXT インデックスはトークンベースのテキスト検索をサポートし、ジオメトリ値に対する SPATIAL インデックスは R ツリーを使用します。MySQL は MEMORY エンジン向けのハッシュインデックスも説明しています。InnoDB は一般的なハッシュインデックスを公開しませんが、アダプティブハッシュインデックスは内部最適化として頻繁にアクセスされる B ツリーページをキャッシュできます。プレフィックスインデックスは長いテキストキーのバイトサイズを削減できますが、選択したプレフィックスが選択性を維持する場合に限ります。

sql
EXPLAIN ANALYZE
SELECT id, created_at
FROM event
WHERE tenant_id = 7
  AND created_at >= '2026-01-01'
ORDER BY created_at, id
LIMIT 100;

インデックスが使用されると仮定せず、実際の行数、ループ回数、時間を確認します。統計情報、カーディナリティの推定、少ない結果セットによって、インデックス走査よりテーブルスキャンが安価になることがあります。

SHOW INDEX は正確な個別値数ではなく、推定カーディナリティを報告します。正当な理由がある場合は ANALYZE TABLE で古い統計を更新し、オプティマイザーの推定を EXPLAIN ANALYZE の測定値と比較します。不可視インデックスを使用すると、InnoDB が維持を続ける間、インデックスが存在しない場合のようにプランをテストできます。

sql
ALTER TABLE event ALTER INDEX event_tenant_created INVISIBLE;
ALTER TABLE event ALTER INDEX event_tenant_created VISIBLE;

代表的なクエリと制約要件を確認するまで、インデックスを削除しないでください。追加の各インデックスはページを消費し、挿入、削除、更新、REDO ログ、バッファープール、バックアップ、レプリケーションの処理を増加させます。したがって、インデックスの選択では、測定された読み取り上の利点と書き込み増幅および運用コストのバランスを取る必要があります。

参照 #

コメント

GitHub で閲覧・コメントする(投稿にはログインが必要です)