技术深度解析
cstore_fdw构建于PostgreSQL的外部数据包装器(FDW)接口之上,该接口最初设计用于连接MySQL或CSV文件等外部数据源。该扩展劫持了这一接口,将数据以列式格式存储在本地。当查询到达时,FDW层会获取列块、解压它们,然后传递给PostgreSQL的执行器。这种架构存在几个根本性限制:
- 无谓词下推:FDW层无法将WHERE子句下推到存储引擎,这意味着即使只有少数行匹配,PostgreSQL也必须获取整个列块。
- 单线程读取:FDW扫描本质上是顺序的,无法利用并行查询执行。
- 事务隔离缺口:cstore_fdw未能完全集成PostgreSQL的MVCC,导致并发写入下可能出现读取不一致。
- 写入放大:更新和删除需要重写整个行组,使其不适合混合工作负载。
Citus的现代列式实现,在Citus 11.0中引入,使用了表访问方法(TAM)——一个允许自定义存储引擎直接插入查询执行器的PostgreSQL扩展点。这与TimescaleDB的超表和ZomboDB的倒排索引所使用的机制相同。TAM方法完全消除了FDW开销:
- 原生谓词下推:列式读取器可以基于元数据(最小值/最大值)跳过整个行组,对于范围查询可将I/O减少高达90%。
- 并行扫描:TAM支持并行顺序扫描,允许多个工作进程同时读取不同的行组。
- 完整MVCC支持:更新和删除通过PostgreSQL的标准事务机制处理,写入操作对于小行会回退到堆表。
- 压缩灵活性:支持ZSTD、LZ4和PGLZ,具有可配置的压缩级别,在典型分析数据集上可实现3-5倍的压缩比。
| 特性 | cstore_fdw (FDW) | Citus Columnar (TAM) |
|---|---|---|
| 谓词下推 | 否 | 是(行组剪枝) |
| 并行查询支持 | 否 | 是(并行顺序扫描) |
| MVCC集成 | 部分 | 完整 |
| 写入性能 | 慢(重写行组) | 快(小行回退到堆) |
| 压缩算法 | ZSTD, LZ4, PGLZ | ZSTD, LZ4, PGLZ(相同) |
| 维护开销 | 手动VACUUM | 通过Citus自动管理 |
| PostgreSQL版本支持 | 9.5 - 13 | 12+(需要TAM) |
| GitHub星标 | 1,785 | 6,500+(Citus主仓库) |
数据要点: 基于TAM的方法在查询并行性和谓词过滤方面实现了数量级的改进,使其在生产分析工作负载中可行,而cstore_fdw仅限于原型设计。
关键参与者与案例研究
主要参与者是Citus Data,于2019年被微软收购,金额未公开(估计超过1亿美元)。该团队已将列式存储集成到Citus扩展中,这现在是PostgreSQL列式存储的推荐路径。最初的cstore_fdw由Citus联合创始人Ozgun Erdogan和Sumedh Pathak创建,作为展示列式存储可行性的副项目。
PostgreSQL列式存储领域的竞争解决方案包括:
- TimescaleDB:使用基于块压缩的超表抽象,针对时间序列数据优化。其压缩对物联网数据可实现90%以上的缩减,但对于通用分析模式灵活性较低。
- Parquet + pg_parquet:一个允许PostgreSQL读写Apache Parquet文件的扩展。适用于数据湖集成,但并非原生存储引擎。
- Hydra(现为Supabase的一部分):一个使用自定义TAM的列式扩展,但自收购以来开发已放缓。
| 解决方案 | 存储引擎 | 最佳用例 | 压缩比 | 写入性能 |
|---|---|---|---|---|
| Citus Columnar (TAM) | 原生TAM | 通用分析 | 3-5倍 | 中等(堆回退) |
| TimescaleDB | 超表 + 块压缩 | 时间序列 | 6-10倍 | 高(仅追加) |
| pg_parquet | 外部文件格式 | 数据湖查询 | 2-4倍 | 低(批量写入) |
| cstore_fdw(已弃用) | FDW | 遗留项目 | 2-3倍 | 低 |
数据要点: Citus Columnar在混合工作负载的压缩和写入性能之间提供了最佳平衡,而TimescaleDB主导时间序列领域。cstore_fdw的弃用将市场整合到基于TAM的解决方案周围。
行业影响与市场动态
cstore_fdw的弃用是一个更大趋势的缩影:PostgreSQL中OLTP与OLAP的融合。历史上,组织运行独立的数据库——PostgreSQL用于事务,Redshift/Snowflake/BigQuery用于分析。PostgreSQL中原生列式存储的兴起威胁要打破这种区分。
关键市场影响:
- 降低总拥有成本:公司