【実務・中級編】 BRINインデックス – PostgreSQL

「B-treeだけがインデックスじゃない」——巨大データを救うBRINの魔法

やあ。今日はちょっとした「インデックスの使い分け」の話をしようか。

PostgreSQLを触り始めてしばらく経つと、インデックスといえば「B-tree」一択だと思い込んでしまう時期があるよね。もちろん、B-treeは万能だ。でも、数億行、あるいは数十億行に達するような「巨大なテーブル」を扱うとき、B-treeは時として足かせになる。インデックスサイズがメモリに乗り切らなくなって、ディスクI/Oが爆発するからだ。

そんなとき、僕が迷わず切り札として取り出すのがBRIN (Block Range Index) だ。

今日は、この「一風変わった、でも最高にクールなインデックス」について、実務的な視点で深掘りしてみよう。

—

BRINは「辞書」ではなく「付箋」

まず、BRINがどうやって動いているか、イメージで理解しよう。

B-treeが「どの値がどこにあるか」を詳細に記録した辞書だとしたら、BRINは「このページ範囲には、だいたいこのくらいの値が入ってるよ」というアバウトな付箋なんだ。

BRINは、テーブルを一定の「ブロック範囲(デフォルトは128ページ)」で区切り、その範囲内の「最小値」と「最大値」だけをメモリに保持する。検索時には、その範囲を見て「お、探している値はこの範囲に収まっている可能性があるな」というブロックだけをスキャンする仕組みだ。

  • メリット: インデックスサイズがB-treeと比べて圧倒的に小さい。数GBのB-treeが、BRINなら数MBで済むことだってある。
  • デメリット: 「範囲」で管理しているから、ピンポイントでレコードを特定するのには向かない。あくまで「大まかな絞り込み」用だ。

—

BRINが真価を発揮する「たった一つの条件」

BRINを使う上で絶対に忘れてはいけないルールがある。それは、「テーブルの物理的な格納順序と、インデックスを貼るカラムの値が相関していること」だ。

例えば、`created_at`(タイムスタンプ)のような、時系列でデータが挿入されるカラム。これにはBRINは最強だ。なぜなら、物理的にも過去のデータは前のブロックに、未来のデータは後ろのブロックに並んでいるからだ。

逆に、ランダムなIDやUUIDのように、値がバラバラに挿入されるカラムにBRINを貼っても、各範囲の「最小値・最大値」が全域をカバーしてしまい、結局「全ブロック読み込み」になってしまう。これじゃあ意味がないよね。

—

実践:BRINを作ってみよう

じゃあ、実際にどう使うか見ていこう。巨大なログテーブルを想定してみるよ。

— ログテーブルの作成(数億行あると想像してくれ)
CREATE TABLE access_logs (
id BIGSERIAL,
user_id INT,
created_at TIMESTAMP,
message TEXT
);

— 普通ならここでB-treeを貼るけど、サイズが肥大化してつらい…
— そこでBRINの登場だ!
CREATE INDEX idx_access_logs_created_at
ON access_logs USING BRIN (created_at)
WITH (pages_per_range = 32);

この `pages_per_range` というオプションがミソだ。

  • 値を小さくする: 精度は上がるけど、インデックスサイズは少し大きくなる。
  • 値を大きくする: インデックスは超軽量になるけど、スキャン効率は落ちる。

ここらへんは、テーブルの総容量と相談しながらチューニングするのがプロの腕の見せ所だ。

—

注意点:運用でハマらないために

現場でBRINを使うときに、必ず後輩に注意していることが2つある。

1. `VACUUM` をサボるな
BRINは、データが更新・削除されると精度が落ちる。`autovacuum` が適切に動いていないと、BRINの付箋情報がどんどん古くなって、検索性能が劣化していくんだ。
2. 「とりあえず全部BRIN」はNG
「B-treeは重いから全部BRINにしよう」なんていうのは悪手だ。頻繁に更新されるカラムや、データが物理的にバラバラなカラムには絶対に使わないこと。

—

まとめ:BRINは「適材適所」の極み

BRINは、いわば「巨大な荒野を走るためのオフロード車」だ。F1カー(B-tree)のように舗装されたサーキットで0.1秒を競うのには向かない。けれど、どこまでも続く巨大なデータという荒野を、少ないリソースで効率よく駆け抜けるには、これ以上の選択肢はない。

「巨大なテーブルでインデックスの容量がヤバい」「時系列データばかり溜まっていく」……そんな悩みを抱えたとき、ぜひ一度BRINを思い出してほしい。

君が扱うデータセットに、BRINという強力な選択肢を加えてみてくれ。きっと、データベースの挙動が今までより少しだけ軽やかに感じられるはずだよ。

それじゃ、また。現場で何か詰まったら、いつでも聞きに来てくれ。

コメント

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