【実務・中級編】 ビットマップヒープスキャン – PostgreSQL

「なぜインデックスがあるのに遅い?」PostgreSQLのビットマップヒープスキャンが教えてくれること

現場でSQLのパフォーマンスチューニングをしていると、必ず一度は壁にぶつかるのが「インデックスを使っているはずなのに、期待した速度が出ない」という現象です。

特に、`EXPLAIN ANALYZE`の結果に `Bitmap Heap Scan` という文字が出てきたとき、「これって何?」と疑問に思ったことはありませんか? 今回は、単なる教科書的な解説ではなく、現場でこの挙動とどう向き合うべきか、深掘りして解説します。

そもそも「ビットマップヒープスキャン」って何者?

PostgreSQLがデータを読み込むとき、大きく分けて二つの戦略があります。

1. Index Scan: インデックスをたどって、その都度テーブルの行を見に行く(ランダムアクセス)。
2. Sequential Scan: テーブルを最初から最後まで全部読み込む(シーケンシャルアクセス)。

ここで、「インデックスは使いたいけど、1行ずつ行ったり来たりするとディスクの読み込み効率が悪いよね」というジレンマを解消するために現れるのが、ビットマップヒープスキャンです。

簡単に言うと、こんな動きをしています。

  • フェーズ1(Bitmap Index Scan): インデックスをスキャンして、条件に合う行の「場所(ポインタ)」をメモリ上のビットマップ(ビットの配列)にマッピングする。
  • フェーズ2(Bitmap Heap Scan): そのビットマップを元に、物理的なディスク上の位置をソートして、効率的に一気にデータを拾いに行く。

一言で言えば、「ランダムアクセスを、効率的な順序に並び替えてから読みに行く」という、かなり頭のいい戦略なんです。

なぜこれが「チューニングのヒント」になるのか

実務で意識してほしいのは、このスキャンが発生しているということは、「PostgreSQLが、インデックス単体でのアクセスよりも、ビットマップを介した方が速いと判断した」という事実です。

例えば、こんなケースを考えてみてください。

— ユーザーテーブルから、特定の年齢層かつ特定ステータスの人を抽出
EXPLAIN ANALYZE
SELECT FROM users WHERE age = 30 AND status = ‘active’;

このとき、`age`にインデックスがあっても、`status`にインデックスがあっても、単独のインデックススキャンでは効率が悪いとオプティマイザが判断した場合、ビットマップスキャンが選択されます。

ここで注意!ビットマップの「メモリ制限」

ここからが現場の知恵です。PostgreSQLには `work_mem` というパラメータがあります。ビットマップを作成するためのメモリ領域なのですが、条件に合う行数が多すぎてビットマップがメモリに入りきらなくなると、ビットマップが「ロス」します。

こうなると、PostgreSQLは精度の低い情報でテーブルを再スキャンする羽目になり、パフォーマンスがガタ落ちします。もし実行計画を見ていて、「Bitmap Heap Scanでやたら時間がかかっている」かつ「検索対象の行数が膨大」なら、`work_mem` のチューニングを検討するサインかもしれません。

実践:どう向き合うべきか?

もし皆さんの環境で、低速なクエリに `Bitmap Heap Scan` が現れたら、以下のチェックリストを試してみてください。

  • インデックスの粒度: 複数のカラムで検索しているなら、複合インデックス(`CREATE INDEX ON users (age, status);`)を作った方が、ビットマップを作る手間が省けて `Index Scan` に切り替わる可能性があります。
  • 統計情報の鮮度: `ANALYZE` は定期的に実行されていますか? 統計情報が古いと、行数を読み違えてビットマップスキャンを選択し、結果として無駄なI/Oが発生します。
  • work_memの確認: `EXPLAIN ANALYZE` に `Lossy` という単語が出ていないか見てください。「Lossy」とあれば、メモリ不足でビットマップが間引かれています。

最後に

ビットマップヒープスキャンは、決して「悪者」ではありません。むしろ、ランダムI/Oを抑えようとするPostgreSQLの「優しさ」です。

ただ、それが頻発しているということは、「今のインデックス設計では、データの探し方が最適化しきれていないよ」というデータベースからのメッセージでもあります。

「とりあえずインデックスを貼る」だけでなく、「どういう順序で読みに行けば効率がいいか」を想像しながら実行計画を眺めてみると、パフォーマンスチューニングはもっと面白くなりますよ。

また現場で詰まったら、いつでも聞きに来てください。一緒に実行計画の海を泳ぎましょう!

コメント

タイトルとURLをコピーしました