PostgreSQLでIoTログ、アクセスログ、金融データなど数億件規模の時系列データを扱う場合、インデックス設計は性能を大きく左右します。特にBRINインデックスとB-treeインデックスは、どちらも検索性能を向上させる仕組みですが、得意とするデータ構造や利用場面が大きく異なります。
大量の時系列データでは、単純に高速なB-treeを選べばよいとは限りません。データの並び方、検索条件、更新頻度、ストレージ容量などを考慮して適切なインデックスを選択する必要があります。
この記事では、PostgreSQLにおけるBRINとB-treeの特徴、数億件規模の時系列データでの選択基準、実際の設計例について詳しく解説します。
PostgreSQLのB-treeインデックスとは
B-treeインデックスは、PostgreSQLで最も一般的に利用される標準的なインデックス方式です。データを木構造で管理し、検索対象の値を効率的に探索できます。
例えば、以下のような検索ではB-treeが非常に効果的です。
SELECT * FROM logs WHERE user_id = 10001;
また、範囲検索にも強く、以下のような条件にも適しています。
SELECT * FROM logs WHERE created_at BETWEEN '2026-01-01' AND '2026-01-31';
B-treeでは対象データを直接特定できるため、高い検索性能を発揮します。ただし、大量データではインデックス自体のサイズが大きくなり、メモリやディスク容量を多く消費するという特徴があります。
PostgreSQLのBRINインデックスとは
BRIN(Block Range INdex)は、大量データ向けに設計されたPostgreSQL独自のインデックス方式です。
B-treeのようにすべての行を個別に管理するのではなく、データページの範囲ごとに最小値・最大値などの要約情報だけを保持します。
例えば、時系列データが以下のように保存されている場合を考えます。
2026年1月1日 00:00:01
2026年1月1日 00:00:02
2026年1月1日 00:00:03
…
時間順にデータが追加されている場合、特定期間の検索では不要なブロックを効率的に除外できます。
BRINは保持する情報量が非常に少ないため、数億件以上の巨大テーブルでも小さなサイズで作成できる点が大きなメリットです。
時系列データでBRINが向いているケース
BRINインデックスが特に効果を発揮するのは、データの物理的な並び順と検索対象の値に相関がある場合です。
代表的な例として、以下のようなデータがあります。
- サーバーアクセスログ
- IoTセンサーデータ
- 株価や取引履歴
- アプリケーションイベントログ
- 監視システムの時系列記録
例えば、毎秒追加されるセンサーデータをtimestamp順に保存している場合、過去1時間分だけ取得する検索ではBRINが非常に効率的です。
また、数億件のログテーブルで「直近7日間だけ確認する」といった用途では、B-treeよりもBRINの方が少ないリソースで十分な性能を発揮する場合があります。
B-treeが向いているケース
B-treeは、検索対象の値がデータ全体にランダムに分散している場合や、特定の行を高速に取得したい場合に向いています。
例えば、以下のような検索ではB-treeが適しています。
SELECT * FROM events WHERE device_id = 'device_12345';
device_idのような値が時系列順に並んでいない場合、BRINでは効率よく対象範囲を絞り込めません。
また、以下のような用途でもB-treeが有利です。
- 主キー検索
- ユーザーID検索
- 注文番号検索
- 特定レコードの取得
「大量データの中から少数の行を正確に探す」場合はB-treeを選択することが基本になります。
BRINとB-treeの比較
| 項目 | B-tree | BRIN |
|---|---|---|
| インデックスサイズ | 大きい | 非常に小さい |
| 検索性能 | 幅広い条件で高速 | データ順序に依存 |
| 大量時系列データ | 容量負荷が大きい | 非常に向いている |
| ランダム検索 | 得意 | 苦手 |
| 作成・更新コスト | 比較的大きい | 小さい |
数億件の時系列データでの選択基準
数億件規模の時系列データでは、以下のポイントを基準に判断するとよいでしょう。
| 条件 | 推奨インデックス |
|---|---|
| timestamp順にデータが追加される | BRIN |
| 特定IDを頻繁に検索する | B-tree |
| 期間検索が中心 | BRIN |
| 1件取得が多い | B-tree |
| ディスク容量を節約したい | BRIN |
実際の大規模システムでは、BRINとB-treeを併用するケースもあります。
例えば、ログテーブルにtimestamp用のBRINインデックスを作成し、ユーザーIDやデバイスIDにはB-treeを作成するといった設計です。
BRINを利用するときの注意点
BRINは万能な高速化手法ではありません。最大のポイントは、データの物理的な並び順が検索条件と一致していることです。
例えば、timestampカラムが存在していても、古いデータと新しいデータがランダムに混在して保存されている場合、BRINの効果は低下します。
そのため、時系列データでは基本的にINSERT順と時間順が一致する設計にすることが重要です。
まとめ
PostgreSQLで数億件の時系列データを扱う場合、BRINとB-treeの選択は「どのような検索をするか」で決まります。
時間範囲でログを取得するような用途では、サイズが小さく大量データに強いBRINが適しています。一方、ID検索や特定レコード取得が多い場合はB-treeが有効です。
実際のシステムでは、時系列カラムにはBRIN、検索頻度の高い識別子にはB-treeというように役割分担させることで、数億件規模でも高速で効率的なPostgreSQL環境を構築できます。

コメント