発展インデックスの種類

カバリングインデックス

定義

カバリングインデックスとは、クエリで参照する全カラムをインデックス側だけで賄えるように設計したもので、テーブル本体アクセス(インデックスオンリースキャン)を不要にする。

「テーブル本体を読まない」インデックス

通常のインデックス検索は、インデックスで該当行を特定してからテーブル本体にアクセスして必要なカラムを取り出します。 カバリングインデックスは、必要なカラムをインデックス側に全部含めることで、テーブル本体アクセスを一切不要にします。

カバリングインデックス(インデックスオンリースキャン)
インデックス (user_id, order_id)

※ ここでは分かりやすさのためソート済みリスト風に描いているが、 実際はB-treeで保持されるので探索は O(log N)。 詳しくは B-treeの仕組み へ。

user_id=1order_id=1001→ 本体を読む
user_id=1order_id=1002→ 本体を読む
user_id=2order_id=1003→ 本体を読む
user_id=3order_id=1004→ 本体を読む
該当行の本体ページを追加で読み取る
テーブル本体
user_id=1order_id=1001amount=50002025-01-01
user_id=1order_id=1002amount=12002025-01-03
user_id=2order_id=1003amount=88002025-01-05
user_id=3order_id=1004amount=33002025-01-06

amount を取得するために、インデックスで見つけた各行についてテーブル本体を追加アクセスする(Row Lookup)。

クエリ SELECT amount FROM orders WHERE user_id = 1 を想定。カバリングにすると amount がインデックスに含まれるためテーブル本体を読む必要が無くなる。

省略されているのは「テーブル本体のページ読み取り」

通常のインデックスは、葉ノードから 行ID を取得したあと、そのIDが指すページを読みに行きます。この追加のページI/Oが、行数が多いクエリでは支配的な時間になる。

通常インデックス: 追加のページ読み取りが発生
B-tree 葉ノードkey = 42→ 行ID (page=1, offset=0)ページ読み込みテーブル本体 Page 1(約8KB)offset 0 · id=42 · Sato · sato@example.comoffset 1 · id=15 · Tanaka · tanaka@example.comoffset 2 · id=83 · Suzuki · suzuki@example.comoffset 3 · id=27 · Ito · ito@example.comインデックスから行IDを取得そのページを読んで該当行を取り出す

カバリングにすると、必要な値がインデックス側に入っているため、この「テーブル本体のページを読む」ステップを完全に省略できます。

カバリング: インデックスだけで完結(ページ読まない)
カバリング葉ノードkey = 42→ 行ID (page=1, offset=0)+ name="Sato"不要テーブル本体 Page 1(約8KB)offset 0 · id=42 · Sato · sato@example.comoffset 1 · id=15 · Tanaka · tanaka@example.comoffset 2 · id=83 · Suzuki · suzuki@example.comoffset 3 · id=27 · Ito · ito@example.com1回のI/O(インデックスだけ)本体ページは読まない

「インデックスオンリースキャン」と呼ばれる

実行計画(EXPLAIN)に「テーブル本体を触っていない」ことを示す文言が現れるのがこのケース(RDBMSごとに用語は異なる)。 テーブルアクセスが省かれるため、行数が多いクエリで劇的に速くなります。

設計のポイント

  • クエリで参照するカラムだけを覆えばよい。SELECT * ではなく必要な列だけを取る
  • ソートや集約に使うカラムを含めておくと、そのままインデックスから結果が返せる
  • 大きなカラムを覆うとインデックスが膨らむので費用対効果を確認する

よくある疑問

Q.INCLUDE付きインデックスとは?
A.多くのRDBMSに、インデックスキーには使わないが値だけをインデックスに保持するためのオプションがあります。これを使うと、キーとしての探索性能を保ちつつ、カバリング用の追加カラムを持たせられます。
Q.カバリングインデックスは常に得?
A.いいえ。インクルードするカラムが多いほどインデックスサイズが増え、更新コストも上がります。頻出クエリに絞って設計するのが基本です。
Q.実行計画で見分けるには?
A.「Index Only Scan」「Using index」など、RDBMSごとに表現は違いますが、いずれも「テーブル本体を触っていない」ことを示す文言が実行計画に現れます。

関連トピック

もっと学びたい方へ(おすすめ書籍)

本セクションはAmazonアソシエイトのリンクを含みます。購入いただくと運営者に紹介料が入る場合があります。

オンライン個別指導

もっと深くDBを学びたい方へ。

たいてっくが、SQL・データベース設計・パフォーマンスチューニング・ IPAデータベーススペシャリスト対策まで、1対1で学習をサポートします。まずは無料相談から。

無料相談を予約する →