pgColumnar 1.0-alpha4 发布
2026年9月17日
Joshua D. Drake
Postgres OpenSource Business SQL Python
pgColumnar 1.0-alpha4 发布说明
源码
文档
产品页面
2026-09-17
pgColumnar 1.0-alpha4 发布说明
发布日期:2026-09-17 上一版本:1.0-alpha3(2026-09-02)
pgColumnar 是 PostgreSQL 的列式表访问方法。这是第四个 alpha 版本。其主题是布局与跳过。表现在可以按希尔伯特曲线(Hilbert curve)布局,这比 Z 序(Z-order)能让相邻键彼此更靠近。星型模式连接现在会跳过事实表分组并拒绝不匹配的行,而且无需被要求就会这样做。磁盘上的原生格式 PGCN v1 未变。现有表的读写方式与之前相同。
此版本需要一条升级命令。参见末尾的"升级"。这次升级是迄今为止所有版本中最小的一次:它添加了两个函数,其他什么都没改。
亮点
- 希尔伯特聚类。
pgcolumnar.cluster_hilbert和pgcolumnar.recluster_hilbert将表按希尔伯特曲线布局。该曲线在位边界处没有跳跃,因此范围过滤器读取的块组(chunk group)更少。在跨两列的 200,000 行上测量,希尔伯特比 Z 序少读 1.24 倍到 2.04 倍的组。 - 星型模式连接默认跳过并拒绝。 串行内哈希连接(Hash Join)现在使用构建侧(build-side)的键来跳过事实表块组并拒绝不匹配的行。
pgcolumnar.enable_join_runtime_filter处于开启状态。 - 宽表的索引驱动读取做更少的 I/O。 一个行组内相邻列的读取被合并为单次读取。
- 并行索引构建现在会使用其工作进程。 每个参与者声明不同的行组。在此版本之前,一个后端读取整个表,而启动的工作进程闲置。
- 规划器不再偏好做远超必要工作的获取型索引扫描(fetching index scan)。 对数万行的相关范围查询现在采用列式扫描。
希尔伯特聚类
pgcolumnar.cluster_hilbert(table, VARIADIC columns) 按希尔伯特顺序重写表。它持有 AccessExclusiveLock,与 CLUSTER 和 VACUUM FULL 一样。pgcolumnar.recluster_hilbert(table, VARIADIC columns) 在 ShareUpdateExclusiveLock 下在线完成相同的工作,因此读写可以继续。
该曲线是"粘性"的。普通的 pgcolumnar.recluster 会维护希尔伯特表,而不是将其转换回去。命名希尔伯特动词是将 Z 序表切换到该曲线的方式。
根据谓词选择曲线。 Z 序适合点查找。希尔伯特在多列范围过滤器上胜出,而随着查询框增大,差距会缩小。当两者看起来接近时,请测量你自己的语料库。参见 docs/best-practices.md 获取指导,以及 pgcolumnar.sort_status 了解表当前有多少处于有序状态。
之所以是两个动词而不是在现有两个动词上加一个参数,是因为 PostgreSQL 无法在任一方向上扩展 cluster(regclass, VARIADIC name[])。带默认值的参数不能位于 VARIADIC 参数之前。
连接加速
针对列式事实表的串行内哈希连接现在会从它已经哈希过的连接键构建一个过滤器。该过滤器做两件事。一个键范围跳过整个事实表块组。一个布隆过滤器(Bloom filter)拒绝不可能匹配的行。
三个测量案例决定了默认设置:
| 事实表 | 结果 |
|---|---|
| 在连接键上聚类 | 20 个块组中移除 19 个,读取 1 个 |
| 分散 | 移除 0 个组,布隆过滤器在 19,800 个不匹配中拒绝超过 15,000 个 |
| 构建侧过大 | 布隆过滤器自行禁用 |
第三个案例是为什么这对所有人都开启。一个什么都帮不上的过滤器会自行关闭。组跳过仍然需要事实表在连接键上聚类。设置 pgcolumnar.enable_join_runtime_filter 为 off 以进行比较。
一个无分组的向量化聚合也可以在一个唯一键内哈希连接上继续运行。唯一维度充当事实表的过滤器,因此折叠不必停止。重复键维度和 LEFT 连接保持在核心计划上。
读取与规划器
- 合并的列读取。 对一个行组中若干列的索引驱动获取,对相邻块发出一次读取,而不是每列一次。
- 并行索引构建。 表访问方法的并行扫描从共享计数器中按参与者声明行组,就像自定义扫描已经做的那样。并行
CREATE INDEX现在会分散到其工作进程上。 - 并行扫描成本。 规划器不再将并行扫描的 I/O 除以工作进程数。PostgreSQL 将 CPU 分散到工作进程,而将磁盘工作视为整体,列式成本现在与之匹配。
- 聚簇索引获取成本。 获取惩罚现在按行收取一项,上限为半个块组。没有它,一个 50,000 行的相关范围会停留在获取型索引扫描上,而它做的工作远多于一次扫描。
正确性修复
- 被截断的列块会被拒绝而不是读取。 一个记录长度超过 4 GB 的块在索引获取路径上被转换为 32 位。因此一次获取可能读到错误的字节并将其报告为数据。两个转换点现在都引发
XX001。 - 合并获取不能读过其缓冲区。 有效性位图复制现在在运行前受块长度限制。
- 投影在 DDL 后存活。 重写会重新记录其投影。
ALTER TABLE ... RENAME COLUMN将新名称带入投影。当投影依赖于该列时,ALTER TABLE ... DROP COLUMN被拒绝。原地TRUNCATE会清除每个投影的存储以及基表。 - 块编解码器释放其缓冲区。 两条路径都放弃了它。
- 对象存储拒绝
s3://和gs://上的 URL userinfo ,正如http(s)://自 #706 以来所做的那样。
已知问题
- 设置编解码器可能使表变大,在高熵文本上(#1074)。 写入器仅在 FSST 以
fsst_min_gain_percent胜过替代方案时才保留它,并且它在块编解码器运行之后测量两边。存储未压缩的 FSST 码从未被比较。在 200,000 行随机十六进制文本上测量,zstd比compression = none多写了 1.777%。lz4未受影响。如果表存储长的高熵文本且大小很重要,请测量两种设置。 - 块编解码器压缩一个随后被丢弃的区域(#1075)。 在不可压缩数据上,这会花费约 25% 更多的写入 CPU。它不影响存储或读取的内容。
升级
安装此构建,然后在每个安装了该扩展的数据库中运行以下命令:
sql
ALTER EXTENSION pgcolumnar UPDATE;
这是必需的。升级会创建 pgcolumnar.cluster_hilbert 和 pgcolumnar.recluster_hilbert。它不更改任何其他内容。没有表数据被转换,没有现有函数被替换,没有目录列被添加,你编写的 SQL 也没有任何变化。
参见 docs/installation.md 获取命令,包括如何列出需要更新的数据库。
范围与限制
- 这是一个 alpha 版本。接口在 1.0 之前可能发生变化。
- 希尔伯特聚类在重写时对整个行组排序。重写后写入的表会偏离顺序,直到下一次重写。
- 连接运行时过滤器适用于直接列式扫描上的串行内哈希连接。它不包裹 LEFT、SEMI、ANTI、CROSS、并行或投影扫描。
- 在 PGXN 上,此版本是 1.0.0-alpha.4,而
CREATE EXTENSION报告 1.0-alpha4。PGXN 要求语义化版本,需要三个整数组成部分。扩展自己的版本有两个。这两个名称指的是同一个版本。
完整的逐项变更列表在 CHANGELOG.md 中。