インデックスオンリースキャンとVisibility Map
クエリをカバーし、Visibility Mapを最新に保つことで、インデックスオンリースキャンを利用できるようにします。
「インデックスオンリースキャンとVisibility Map」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
インデックスオンリースキャンとは
通常、インデックス検索は行 ID(TID)を返すため、実際の行を読み取るにはテーブルにもアクセスする必要があります。Index-Only Scan では、インデックスだけを使ってクエリに応答し、ヒープにはアクセスしません。大幅に高速化できます。
条件
Index-Only Scan には次の条件が必要です。
- SELECT するすべての列がインデックスに含まれていること
- 行のページが、visibility map で「すべて可視」とマークされていること
Visibility Map
テーブルの各ページに対応するビットマップです。ビットが設定されている場合、そのページのすべての行がすべてのトランザクションから可視であることを示します。VACUUM がこれを管理します。これがないと、PostgreSQL は可視性を確認するためにヒープへアクセスする必要があります。
クエリをインデックスオンリーにする
必要なすべての列をカバーします。
-- Query:
SELECT id, email FROM users WHERE id = 42;
-- Without an index on (id, email), only an Index Scan that visits the heap is possible.
-- With this:
CREATE INDEX users_id_email_idx ON users (id, email);
-- Or better:
CREATE INDEX users_id_email_idx ON users (id) INCLUDE (email);
-- The query can be index-only.INCLUDE
キーではない列を含めるカバリングインデックスです(PG 11 以降)。列はリーフに格納されますが、順序付けには使用されないため、挿入コストに影響しません。
CREATE INDEX users_id_idx ON users(id) INCLUDE (email, full_name);
SELECT id, email, full_name FROM users WHERE id = 42;
-- Index-only scan if visibility map allows.それでもヒープにアクセスする場合
大量の書き込みの後では、visibility map が古くなっている可能性があります。VACUUM(FULL なし)を実行して更新してください。
VACUUM (VERBOSE) users;
-- "scanned X pages, X of which are visible"
-- More visible pages = more Index-Only Scans possible.インデックスオンリースキャンの確認
EXPLAIN で確認できます。
EXPLAIN ANALYZE
SELECT id, email FROM users WHERE id = 42;
-- Index Only Scan using users_id_email_idx on users
-- Index Cond: (id = 42)
-- Heap Fetches: 0 ← key numberHeap Fetches から分かること
「Heap Fetches: 0」は、すべてのデータをインデックスから取得できており、理想的な状態です。「Heap Fetches: N」は、N 行でヒープへのアクセスが必要だったことを示します(visibility map のビットが設定されていません)。Autovacuum の実行後は、通常 Heap Fetches が減少します。
INCLUDE と複合インデックスの使い分け
- SELECT するだけで、フィルタリングやソートには使用しない列には INCLUDE を使用します
- その列でもフィルタリングやソートを行う場合は、複合インデックス(キー)を使用します
INCLUDE を使うとインデックスが狭くなり、書き込みも高速になります。
インデックスの膨張はインデックスオンリースキャンを妨げる
膨張したインデックスはページ数が増えるため、インデックスオンリースキャンでも読み取る量が増えます。インデックスを VACUUM し、膨張が大きくなったら再インデックス化してください。
すべてをカバーしない
インデックスに列を追加しすぎると、書き込みが遅くなり、インデックスも巨大になります。頻繁に読み取る処理だけをカバーしてください。
カバーとしてのマテリアライズドビュー
特定のレポートを極めて高速に読み取りたい場合は、マテリアライズドビューとインデックスの組み合わせが、任意の計算列を持つ「カバリングインデックス」のように機能します。
まとめ
Index-Only Scan は最速の読み取り経路です。
- SELECT するすべての列がインデックスに含まれている必要があります
- INCLUDE を使うと、キーではない列を低コストで追加できます
- visibility map が「すべて可視」と示している必要があります — VACUUM が最新の状態に保ちます
- EXPLAIN では Heap Fetches: 0 が目標です
クイックチェック
Index Only Scan ノードがあるにもかかわらず、EXPLAIN に Heap Fetches: 100,000 と表示されています。一般的な対策は何ですか?
AI チューターと学ぶ SQL — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 46
- レッスン
- 183
よくある質問
「インデックスオンリースキャンとVisibility Map」レッスンは無料ですか?
はい。「インデックスオンリースキャンとVisibility Map」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「インデックスオンリースキャンとVisibility Map」で何を学びますか?
クエリをカバーし、Visibility Mapを最新に保つことで、インデックスオンリースキャンを利用できるようにします。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「インデックスオンリースキャンとVisibility Map」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- MVCCと肥大化の原因
- VACUUM、autovacuum、vacuum_cost_delay
- ANALYZEとpg_statistic
- インデックスオンリースキャンとVisibility Map