PostgreSQLNotes

第 10 章:BRIN 与 SP-GiST

zjc 于 2026-01-10 发布

这是《PostgreSQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 BRIN 适合超大规模且物理顺序与时间或自增字段强相关的表;SP-GiST 适合空间划分、前缀和不平衡树结构。

10.1 BRIN

BRIN(Block Range Index)不索引每一行,而是记录连续数据块的范围摘要。

Block 1-128: min created_at = 08-01, max = 08-02
Block 129-256: min created_at = 08-02, max = 08-03

创建:

CREATE INDEX idx_events_created_brin
ON events USING BRIN (created_at);

查询:

SELECT count(*)
FROM events
WHERE created_at >= '2026-08-25'
  AND created_at < '2026-08-26';

10.2 BRIN 适合场景

条件 说明
表很大 大表收益明显
物理顺序相关 append-only 时间日志
查询范围明确 按时间窗口
索引空间敏感 B-Tree 太大
可接受粗粒度 不要求精确定位

不适合随机写入后物理顺序混乱的数据,除非先按查询键重写。

10.3 BRIN 参数

CREATE INDEX idx_events_created_brin
ON events USING BRIN (created_at)
WITH (pages_per_range = 64);
参数 影响
pages_per_range 小 更精准,索引更大
pages_per_range 大 更小,扫描范围更粗

可以配置自动汇总:

ALTER TABLE events
SET (autosummarize = on);

10.4 SP-GiST

SP-GiST 支持空间划分树,适合数据天然可分区且不平衡的结构。

常见用途:

类型 用途
text 前缀匹配
point 空间划分
inet 网段
range 范围

前缀索引:

CREATE INDEX idx_hosts_prefix
ON hosts USING SPGIST (name prefix_ops);

网段:

CREATE INDEX idx_ip_network
ON access_log USING SPGIST (client_ip inet_ops);

10.5 索引选择

查询 首选
等值 / 范围 / 排序 B-Tree
纯等值高基数 可评估 HASH
JSON / 数组 / 全文 GIN
空间 / 范围重叠 GiST
大表时间 append BRIN
前缀 / 网段 / 划分结构 SP-GiST

10.6 验证索引效果

EXPLAIN (ANALYZE, BUFFERS)
SELECT *
FROM events
WHERE created_at >= now() - interval '1 hour';

观察:

  1. 扫描节点;
  2. Rows Removed by Filter;
  3. Shared Hit / Read;
  4. 执行时间;
  5. 索引大小。

本章小结

BRIN 用极小空间换取粗粒度过滤,适合顺序性强的大表。SP-GiST 面向可划分结构。索引选择先看数据分布和操作符,再看空间和写入成本。

思考题

  1. BRIN 为什么适合 append-only 日志表?
  2. pages_per_range 如何权衡?
  3. SP-GiST 适合什么数据结构?
  4. BRIN 如何验证扫描收益?
  5. 什么时候 B-Tree 优于 BRIN?