こんにちは!データベースの世界へようこそ。
今日は、PostgreSQLのパフォーマンスチューニングにおいて避けては通れない「インデックスの読み方」についてお話しします。
エンジニアとして働いていると、「インデックスを貼ったのにクエリが遅い!」なんて悩みにぶつかることは一度や二度じゃないですよね。そんな時、実行計画(EXPLAIN)を見ると、「Index Scan」ではなく「Bitmap Index Scan」という見慣れない言葉が出てくることがあります。
これ、一体何が起きているのか?初心者の方にもわかるよう、身近な例えで紐解いていきましょう。
—
膨大な書類を探す「図書館」を想像してみて
あなたが巨大な図書館の司書だとします。そこには何百万冊という本が並んでいます。
1. Index Scan:ピンポイントで探しに行く
「『吾輩は猫である』というタイトルの本をちょうだい!」と言われたらどうしますか?
インデックス(索引)を見て、その本の場所を特定し、そこへ一直線に歩いて行って、本を一冊だけ引き抜きますよね。
これが Index Scan(インデックススキャン) です。
狙った獲物をピンポイントで取りに行くので、非常に速い。でも、もし「夏目漱石の作品を全部持ってきて」と言われたらどうなるでしょう? 一冊ずつ探しに行っては戻り、また探しに行っては戻り……。これでは、何度も書庫を行ったり来たりして、足が棒になってしまいますよね。
2. Bitmap Index Scan:一度にまとめて地図を作る
ここで登場するのが Bitmap Index Scan(ビットマップインデックススキャン) です。「夏目漱石の作品」を全部集める必要がある時、賢い司書さんはこうします。
1. まず、インデックスを見て「該当する本の場所」のリストを頭の中で作る(これがビットマップ=地図です)。
2. 「ここらへんに何冊かあるな」という情報を、整理された地図として一度に手に入れる。
3. その地図を手に、書庫を「効率的なルート」で一度だけ巡回して、必要な本をまとめて回収する。
つまり、「バラバラの場所を何度も往復する」のではなく、「場所を事前に整理して、最短ルートで一気に回収する」のがこの手法なんです。
—
なぜBitmap Index Scanが選ばれるのか?
データベースにとって、一番の敵は「ランダムアクセス」です。HDDやSSDのディスクからデータを読み取る際、あちこちにヘッドを飛ばしたり、細切れに読みに行くのは、実はすごく時間がかかる作業なんですよ。
Bitmap Index Scanは、以下のようなシチュエーションでPostgreSQLが「よし、こっちの方が効率的だ!」と判断して選んでくれます。
- 一度に大量のデータを取り出すとき:
先ほどの例のように、対象がそこそこ多い場合、一つずつ読みに行くより「地図」を作ってから読みに行ったほうが、結果的にトータルコストが安くなるんです。
- 複数の条件を組み合わせるとき:
「年齢が20代」かつ「東京都に住んでいる」という検索をする場合、それぞれのインデックスから作った「地図」を重ね合わせて(ビット演算して)、ターゲットとなる場所を絞り込んでから読みに行くことができます。
—
まとめ:難しく考えすぎないで
「Index Scan」と「Bitmap Index Scan」、どちらが優れているかという議論ではありません。あくまで「その時その時の検索条件に合わせて、データベースが選んだ最善の戦術」なんです。
- Index Scan:一撃必殺。ピンポイントの検索に最適。
- Bitmap Index Scan:効率重視のまとめ取り。中規模〜大規模な検索で力を発揮。
もし皆さんが書いたクエリの実行計画で「Bitmap Index Scan」が出てきたら、データベースが「今回は数が多いから、効率的にルートを回るね!」と頑張ってくれている証拠です。
「おっ、賢い動きしてるな」と温かい目で見てあげてくださいね。
データベースの奥深さは、こうした「効率の追求」を知ることで、もっともっと楽しくなりますよ。また次回の記事でお会いしましょう!
コメント