分区与扩展
分区解决单个逻辑大表的物理组织和生命周期管理问题,扩展解决数据库内核能力的组合与扩充问题。两者都能改变系统边界,但不自动解决分布式写入和高可用。
声明式分区
PostgreSQL 把一个逻辑分区表映射为多个物理分区 Relation。父表负责逻辑定义,实际行根据分区键路由到叶子分区。
| 策略 | 规则 | 常见用途 |
|---|---|---|
| Range | 按不重叠的连续范围 | 时间序列、账期、递增编号 |
| List | 按离散值集合 | 区域、租户类别、状态集合 |
| Hash | 对分区键求哈希余数 | 数据无自然范围但需要均匀拆分 |
分区可以继续子分区,形成多级结构。层次过深或分区数量过多会增加规划、元数据、锁和维护成本。
分区裁剪
优化器根据分区边界和查询条件排除不可能匹配的分区。裁剪依赖谓词是否能与分区键规则对应,不是只要建了分区就会发生。
分区内索引与分区裁剪是两层能力:先排除分区,再在剩余分区中选择扫描路径。分区表上的索引定义会管理各分区的对应索引,但物理上仍是多个独立索引。
生命周期管理
分区的主要价值经常不是单条查询更快,而是能够以分区为单位:
- 快速挂载或卸载历史数据。
- 删除整个过期分区,避免大批量 DELETE 产生大量 Dead Tuple 和 WAL。
- 对热点与冷数据采用不同表空间、索引和维护策略。
- 缩小 VACUUM、ANALYZE、备份或批处理操作的管理范围。
选择分区键时应优先考虑数据淘汰边界和高频查询过滤条件。把高基数字段直接做成大量 List 分区,通常会把数据问题转化为元数据问题。
Extension 模型
Extension 把 SQL 对象和底层模块作为一个有版本的安装单元管理,可以包含类型、函数、操作符、索引 Operator Class、FDW 和后台 Worker。
| 扩展或类别 | 主要能力 |
|---|---|
| PostGIS | 空间类型、坐标系、空间函数与 GiST/SP-GiST 索引能力 |
| pg_trgm | Trigram 相似度、模糊匹配及 GiST/GIN Operator Class |
| pg_stat_statements | 聚合 SQL 执行统计,用于识别高成本语句 |
| postgres_fdw | 访问其他 PostgreSQL 数据库并支持部分谓词、连接下推 |
| 时序或向量扩展 | 增加特定领域的数据类型、索引或执行能力 |
扩展不是普通客户端依赖。物理备库需要有兼容的二进制模块,升级数据库大版本时也必须确认扩展支持矩阵、升级脚本和备份恢复方式。
JSONB 与关系模型
JSONB 会把输入解析为二进制结构,支持包含查询和 GIN 索引,适合属性稀疏、结构演进或需要整体保存的嵌套对象。它不应替代所有关系建模:
| 更适合关系列 | 更适合 JSONB |
|---|---|
| 稳定、频繁过滤和连接的字段 | 变化快、稀疏或不同类型对象拥有不同属性 |
| 需要强类型、外键和精细约束 | 需要保存整体文档结构 |
| 依赖准确列统计和常规索引 | 主要进行包含、键存在或文档返回 |
混合模型通常把标识、状态、时间、关联键等稳定字段保留为普通列,把非核心扩展属性放入 JSONB。