「PostgreSQLで数億行のテーブルを扱うことになった。でも、B-treeインデックスを作るとインデックスサイズだけでディスクを食いつぶしちゃうし、更新のたびにインデックスの肥大化が止まらない……」
そんな頭の痛い悩みを抱えたことはないだろうか?
今日は、そんな巨大データという「モンスター」と戦うための隠し武器、BRIN(Block Range Index)について話そう。教科書的な説明はドキュメントに譲るとして、今回は「現場でどう使うのが賢いのか」という視点で掘り下げていくよ。
—
BRINって何者?
一言で言えば、「巨大テーブルにおける『大まかな目次』」だ。
B-treeインデックスが「特定の値をピンポイントで探すための正確な地図」だとしたら、BRINは「このブロックからこのブロックまでは、値の範囲がここからここまでですよ」という「ざっくりとした範囲リスト」なんだ。
仕組みはとてもシンプル。テーブルを物理的な「ブロック範囲(デフォルトは128ブロック)」で区切り、その範囲内に存在するデータの「最小値」と「最大値」だけを保持する。
だから、圧倒的にインデックスサイズが小さい。 数百GBのテーブルでも、BRINなら数MBで済むこともある。これ、運用コストを考えると夢のような話だろ?
—
どんな時に輝くのか?
BRINが真価を発揮するのは、「データが物理的な並び順と相関関係にあるとき」だ。
一番の例は、時系列データ。`created_at` のようなタイムスタンプ順にデータが挿入されるテーブルなら、物理ディスク上にも古いデータから順に並んでいるはずだよね。この場合、BRINは最高のパフォーマンスを発揮する。
逆に、ランダムなID(UUIDなど)が主キーのテーブルにBRINを張っても、ブロックごとの範囲が「0から最大値まで」になってしまい、検索効率はゴミ同然になる。ここは注意してくれ。
—
実践:BRINを作ってみよう
例えば、ログテーブルがあるとしよう。
— 巨大なログテーブル
CREATE TABLE app_logs (
id BIGSERIAL,
created_at TIMESTAMP NOT NULL,
log_level TEXT,
message TEXT
);
— 普通ならここにB-treeを貼るけど、インデックスが巨大化しすぎる…
— そこでBRINの出番!
CREATE INDEX idx_brin_created_at ON app_logs USING BRIN (created_at);
これだけで、`created_at` を条件にした検索が爆速になる。
ちょっとしたコツ:pages_per_range
デフォルトでは128ブロックで1つの範囲を作るけど、これを調整することで精度とサイズのバランスを変えられる。
CREATE INDEX idx_brin_created_at_fine
ON app_logs USING BRIN (created_at)
WITH (pages_per_range = 32);
`pages_per_range` を小さくすれば、インデックスの精度は上がる(範囲が狭くなるから)けど、サイズは増える。逆に大きくすれば、インデックスは極小になるけど、検索時にスキャンする範囲が広くなる。このあたりは、実際にデータを投入した後に `EXPLAIN ANALYZE` を叩きながら調整するのがプロの流儀だ。
—
現場で気をつけるべき「罠」
BRINを使う上で、いくつか「これだけは知っておけ」というポイントがある。
1. 「並び順」が命
もしデータが時系列順に格納されていない場合(例えば、古いデータをDELETEしてそこに新しいデータをINSERTし続けるようなケース)、物理的な並び順とインデックスの範囲が一致しなくなる。そうなるとBRINはただの重りだ。必要なら `CLUSTER` コマンドで物理的に並び替えてあげる必要がある。
2. 更新に弱い
BRINは、頻繁に値が書き換わるようなカラムには向かない。一度作成したブロック範囲の最小・最大値がすぐに古くなってしまうからね。基本は「追記型」のデータで使おう。
3. 完璧な一致検索には向かない
B-treeのような「=(イコール)」検索よりも、「BETWEEN」や「>」「<」といった範囲検索でこそ真価を発揮する。
---
まとめ:使い分けがエンジニアの腕の見せ所
結局のところ、データベース設計に「銀の弾丸」なんてない。
- ピンポイントの検索が必要なら B-tree
- 巨大テーブルで範囲検索を高速化したいなら BRIN
この使い分けができるだけで、お前の作るシステムの運用コストやパフォーマンスは劇的に変わるはずだ。
「とりあえずインデックスを貼る」んじゃなくて、「データの物理的な並びと検索パターンを想像して、最適な手法を選ぶ」。これができるエンジニアは、現場で間違いなく重宝される。
もし君のプロジェクトに、肥大化しすぎて困っている数億行のログテーブルがあったら、ぜひ一度 BRIN を試してみてくれ。その軽さと速さに、きっと驚くはずだから。
それじゃあ、また現場で会おう。健闘を祈る!
コメント