压缩功能完全不需要 PG 内核修改TimescaleDB 的压缩和列存功能是纯 PostgreSQL 扩展实现不需要任何 PG 内核补丁。可以在原生的 PostgreSQL 14/15/16/17 上直接安装使用。一、压缩功能如何独立实现1. 自定义数据类型 — 标准CREATE TYPE压缩后的列值存储为一个自定义的变长类型compressed_data完全通过标准 SQL 注册-- sql/pre_install/types.post.sql CREATE TYPE _timescaledb_internal.compressed_data ( INTERNALLENGTH VARIABLE, STORAGE EXTERNAL, -- 告诉PG这个类型的数据存外部(TOAST里) ALIGNMENT double, INPUT ...compressed_data_in, -- 文字输入(用于COPY/INSERT) OUTPUT ...compressed_data_out, -- 文字输出(用于SELECT) RECEIVE ...compressed_data_recv, -- 二进制输入 SEND ...compressed_data_send -- 二进制输出 );这个自定义类型的 C 结构体就是CompressedDataHeader// compression.h typedef struct CompressedDataHeader { char vl_len_[4]; // PG变长类型标准头部 uint8 compression_algorithm; // 算法标记 // 后面跟着算法特定的压缩数据... } CompressedDataHeader;完全在 PG 标准的变长类型框架内工作— PG 通过vl_len_管理存储大小通过 TOAST 机制自动处理超长数据的切分和压缩。2. 压缩算法实现 — 纯 C 代码不依赖 PG所有压缩算法都在tsl/src/compression/algorithms/下独立实现算法实现依赖DELTADELTAdeltadelta.c自实现的 delta-of-delta zigzag simple8b_rleGORILLAgorilla.c自实现的 XOR 浮点数压缩DICTIONARYdictionary.c利用 PG 的 hash/lookup 函数字典编码完全自实现ARRAYarray.c全自实现压缩后数据交给 PG TOASTBOOLbool_compress.c自实现的 bitmap simple8b_rle没有调用 PG 内核的任何压缩函数。压缩和解压都是纯数学运算不需要 PG 提供任何特殊支持。3. 优化器集成 — 标准 PG HooksTimescaleDB 通过 PG 标准的 Hook 机制注入压缩逻辑Hook作用post_parse_analyze_hook检测查询是否涉及压缩表触发后续处理create_upper_paths_hook注入DecompressChunkPath自定义扫描路径ProcessUtility_hook拦截 DDL 将其路由到压缩chunk这些 Hook 都是 PG 官方文档中明确的扩展点存在于原生 PG 中。4. 执行器集成 — 标准 CustomScan读取时的解压缩通过 PG 的CustomScan节点实现exec.c// 这是一个标准的 CustomScan 状态节点 static CustomExecMethods decompress_chunk_state_methods { .BeginCustomScan decompress_chunk_begin, .ExecCustomScan NULL, // 运行时二选一 (fifo/heap) .EndCustomScan decompress_chunk_end, .ReScanCustomScan decompress_chunk_rescan, .ExplainCustomScan decompress_chunk_explain, };子计划扫描压缩chunk的表DecompressChunk节点对每个返回的压缩行batch解压输出解压后的行给上层节点。二、列存 (Hypercore) 功能Hypercore 是 TimescaleDB 的列存引擎同样不需要 PG 内核修改。通过 PG 的 Table Access Method API 实现标准 SQL 注册-- sql/pre_install/tam.sql CREATE ACCESS METHOD hypercore TYPE TABLE HANDLER ts_hypercore_handler;C 代码中注册标准TableAmRoutine// tsl/src/hypercore/hypercore_handler.c static const TableAmRoutine hypercore_methods { .type T_TableAmRoutine, .scan_begin hypercore_beginscan, .scan_end hypercore_endscan, .tuple_insert hypercore_tuple_insert, .multi_insert hypercore_multi_insert, .tuple_delete hypercore_tuple_delete, .tuple_update hypercore_tuple_update, .relation_vacuum hypercore_vacuum_rel, // ... 所有标准 TAM 回调 ... };Table Access Method 是 PG 12 引入的标准 API用于实现可插拔存储引擎。Hypercore 完全通过这个接口工作ALTER TABLE chunk SET ACCESS METHOD hypercore将 chunk 切换到列存引擎检测方式rel-rd_tableam hypercore_routine()— 比较函数指针标准做法不需要修改 PG 任何内核代码Hypercore 的列存优势相比传统行存压缩列级向量化谓词评估— 通过 Arrow C Data Interface 批量处理列数据更高效的批量解压— 按列解压只解压查询需要的列透明的 DML 支持— 压缩/未压缩数据在同一 chunk 中共存三、唯一的非标准要求shared_preload_librariesTimescaleDB 需要shared_preload_libraries timescaledb# postgresql.conf shared_preload_libraries timescaledb这是因为 TimescaleDB 的Loader 组件必须在 PG 启动时加载设置post_parse_analyze_hook以拦截所有查询初始化后台 worker 调度器用于自动压缩策略初始化共享内存这是 PG 扩展生态中非常常见的做法如pg_stat_statements、pg_cron、postgis都类似不是内核修改只是配置要求。总结┌─────────────────────────────────────────────────────────────────┐ │ TimescaleDB 压缩/列存 纯 PG 扩展 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ PG 内核层 TimescaleDB 层 │ │ ┌──────────┐ ┌──────────────────────────────┐ │ │ │ CREATE │──────────│ compressed_data 自定义类型 │ │ │ │ TYPE │ │ (变长类型TOAST管理存储) │ │ │ ├──────────┤ ├──────────────────────────────┤ │ │ │ CREATE │──────────│ hypercore Table Access Method │ │ │ │ ACCESS │ │ (标准 TAM 接口实现) │ │ │ │ METHOD │ ├──────────────────────────────┤ │ │ ├──────────┤ │ 压缩算法 (纯C实现无PG依赖) │ │ │ │ Custom │──────────│ • DELTADELTA (整数类型) │ │ │ │ Scan │ │ • GORILLA (浮点类型) │ │ │ │ 节点 │ │ • DICTIONARY (文本类型) │ │ │ ├──────────┤ │ • BOOL (布尔类型) │ │ │ │ Planner │──────────│ • ARRAY (fallback) │ │ │ │ Hooks │ ├──────────────────────────────┤ │ │ ├──────────┤ │ DecompressChunk (CustomScan) │ │ │ │ standard │ │ 谓词下推到 min/max 元数据列 │ │ │ │ PG APIs │ │ Batch 解压 → 逐行输出 │ │ │ └──────────┘ └──────────────────────────────┘ │ │ │ │ 需要: shared_preload_libraries timescaledb │ │ 不需要: 任何 PG 内核补丁 │ └─────────────────────────────────────────────────────────────────┘核心结论TimescaleDB 的压缩和列存是对 PG 扩展 API 的深度利用体现了 PG 扩展框架的强大能力但完全不需要修改 PG 内核源码。同样的技术栈也用于其他 PG 扩展如 Citus 的分布式查询、pg_partman 的分区管理。