pgColumnar 1.0-alpha4 于 2026 年 9 月 17 日发布,距离 1.0-alpha3 只有两周。这一版的主题很明确:改进列式数据的布局,并让查询更有效地跳过不相关的数据组。对于在 PostgreSQL 中运行分析型查询的团队来说,重点不只是“数据按列存储”,而是“相关数据能否被放在更近的位置,以及无关数据能否尽早不读”。
为什么布局方式会影响列式查询
列式存储通常会把数据按列组织,并进一步划分为多个数据组。查询只需要少数列时,可以避免读取整行;如果谓词还能判断某个数据组不可能匹配,就可以直接跳过这个数据组。
这使得数据布局成为性能的一部分。假设事实表同时包含 customer_id、product_id、event_date 和 amount,查询经常按照多个维度过滤。如果相关键值在物理布局上相互靠近,数据组的范围更集中,跳过判断就更容易生效。反过来,随机写入或不合适的排序可能让每个数据组都混入大量不同范围,最终不得不读取更多数据。
Hilbert 曲线与 Z-order 的差别
alpha4 支持使用 Hilbert curve 组织表布局。Z-order,也称 Morton order,会把多个维度的坐标交错编码成一条线;Hilbert curve 则通过连续曲线遍历多维空间。
直观地说,Hilbert 曲线更重视局部连续性:在多维空间中相邻的键,通常更有机会在一维存储顺序中保持接近。对于多列过滤条件,这可能形成更紧凑的数据组,从而提升谓词下推和数据跳过的收益。
这并不意味着 Hilbert 布局在所有负载中都必然更快。布局需要结合实际过滤列、数据分布、批量写入方式和查询模式评估。只有当查询经常在多个维度上筛选,并且数据组的跳过可以显著减少读取量时,布局优化才有明显价值。
星型连接中的事实表跳过
本版本还改进了星型模式下的连接处理:查询在连接维表和事实表时,可以跳过不匹配的事实表数据组。
典型场景是:
- 事实表保存大量销售或事件记录;
- 维表保存客户、产品、地区等相对较小的数据;
- 查询先用维表条件筛选出一小部分键,再连接事实表;
- 事实表中绝大多数数据组都不可能包含这些键。
在这种情况下,优化器或执行层如果能利用数据组的键范围、统计信息或布局特征,就可以避免扫描全部事实数据。需要注意的是,“支持跳过”不等于每条星型连接都会自动获得收益。维度过滤条件的选择性、事实表的数据分布、连接列的布局以及统计信息质量都会影响结果。
可以这样建立一个最小验证环境
下面的示例使用 PostgreSQL 和 pgColumnar 的典型用法创建一个小型事实表,并通过 EXPLAIN 观察查询计划。示例中的 USING columnar 是可直接改造的基础写法;Hilbert 布局的具体建表参数或管理命令应以所使用的 alpha4 构建版本文档为准,因为该功能仍处于 alpha 阶段。
运行前准备一个已经安装并允许加载 pgColumnar 的 PostgreSQL 实例:
CREATE EXTENSION IF NOT EXISTS columnar;
DROP TABLE IF EXISTS sales_fact;
CREATE TABLE sales_fact (
event_date date,
customer_id bigint,
product_id bigint,
region text,
amount numeric(12, 2)
) USING columnar;
INSERT INTO sales_fact (event_date, customer_id, product_id, region, amount)
SELECT
date '2026-01-01' + (g % 90),
(g % 10000) + 1,
(g % 1000) + 1,
CASE g % 4
WHEN 0 THEN 'east'
WHEN 1 THEN 'west'
WHEN 2 THEN 'north'
ELSE 'south'
END,
round((random() * 500)::numeric, 2)
FROM generate_series(1, 1000000) AS s(g);
ANALYZE sales_fact;
EXPLAIN (ANALYZE, BUFFERS)
SELECT product_id, sum(amount) AS revenue
FROM sales_fact
WHERE event_date >= date '2026-02-01'
AND event_date < date '2026-03-01'
AND region = 'east'
GROUP BY product_id
ORDER BY revenue DESC
LIMIT 20;
这个实验的重点不是单次执行时间,而是建立基线:记录计划、实际读取的缓冲区和运行耗时,然后再用 alpha4 支持的 Hilbert 布局方式重建一份表,使用同样的数据和查询进行对比。建议至少比较以下指标:
- 扫描的数据组数量或等价的跳过信息;
Buffers中的读取量;- 冷缓存和热缓存下的执行时间;
- 不同选择性过滤条件下的表现;
- 批量追加数据后性能是否仍然稳定。
如果要验证星型连接,可以补充一个小维表,并让维表条件只选出少量客户:
DROP TABLE IF EXISTS customer_dim;
CREATE TABLE customer_dim (
customer_id bigint PRIMARY KEY,
segment text
);
INSERT INTO customer_dim
SELECT
g,
CASE WHEN g <= 100 THEN 'target' ELSE 'other' END
FROM generate_series(1, 10000) AS s(g);
ANALYZE customer_dim;
EXPLAIN (ANALYZE, BUFFERS)
SELECT sum(f.amount)
FROM sales_fact AS f
JOIN customer_dim AS d
ON d.customer_id = f.customer_id
WHERE d.segment = 'target';
如果该查询仍然读取了大量事实表数据,不要立刻判断功能无效。先确认事实表是否按照合适的维度组织、数据是否以足够大的批次写入、统计信息是否最新,并检查 alpha4 版本是否要求额外的布局配置。
采用前要留意的边界
pgColumnar 1.0-alpha4 仍是 alpha 版本,适合在隔离环境中验证,而不应仅凭一个微型测试就迁移核心生产负载。布局通常是写入和重组阶段的决策:更好的查询跳过能力可能伴随重写成本、批量导入约束或维护复杂度。
可以用下面的清单推进评估:
- 先挑选真正以分析读取为主、更新模式相对简单的事实表;
- 用生产级数据分布,而不是均匀随机数据做基准;
- 分别测试单列过滤、多列过滤和星型连接;
- 对比 Hilbert 布局与现有布局,而不是只测一个绝对数字;
- 记录装载时间、存储体积、查询延迟和重建成本;
- 为 alpha 功能设置回滚路径,并固定测试版本。
alpha4 的价值在于把列式存储的优化从“少读几列”推进到“少读几个数据组”。如果你的 PostgreSQL 分析工作负载具有明显的多维过滤和星型连接特征,Hilbert 布局与事实表跳过值得进入基准测试清单,但最终选择仍应由真实数据和真实查询决定。