PostgreSQL 时间序列扩展 - TimescaleDB
TimescaleDB 介绍
TimescaleDB 是一个基于 PostgreSQL 的时间序列数据库扩展(不是独立数据库),通过安装扩展把 Postgres 变成能高效处理时序数据的引擎,兼容所有 Postgres 生态。TimescaleDB 使用场景下的数据带有 3 个明显的特征:
- 带时间戳:数据中包含时间戳字段,用于记录数据的采集时间
- 写入数据量大:持续高频追加
- 按时间查询:特定时间区间内计算聚合、趋势、同比等指标
六大核心概念
Hypertable(超表)
对用户呈现的 “一张表”,内部按时间自动拆分成多张物理子表。
- 超表本身不存数据,只存定义和 chunk 元信息
- 每次 INSERT 按
策略自动路由到对应 chunk - 创建超表后,应用层依然像操作普通 Postgres 表一样读写,无需关心底层分片
- 支持二级分区,将单个时间块再打散到多个 chunk,避免单个 chunk 过大、提升写入并发
Chunk(数据块)
Chunk 是超表的基本单位,每个 chunk 包含一定时间范围内的数据。
- 一个 chunk 对应一个物理子表,名字形如
_hyper_X_Y - 查询命中时间条件时,TimescaleDB 会自动做分区裁剪(partition pruning),只扫描相关 chunk,跳过无关时间范围,这是时序查询快的核心原因
- chunk 的数量、大小可通过
chunk_time_interval调优:写入越密集,应设越小的区间以避免单 chunk 过大;查询跨度越大,适当放大区间减少 chunk 数量 - 可通过
timescaledb_information.chunks视图查看每个 chunk 的时间范围与体积
Compression(压缩)
TimescaleDB 的压缩不是简单的列存 ZIP,而是列式压缩 + 时序专用编码结合:
- 默认对 chunk 启用压缩后,数据从行存转为列存,并对数值列使用 delta-of-delta、GORILLA、字典编码等算法
- 典型时序场景(高频、列相关性高)可获得 90%+ 的空间压缩比
- 压缩是按 chunk 异步进行的,默认只压缩"较旧、不再频繁写入"的 chunk,避免冻结正在写入的数据
- 压缩后的 chunk 仍然可查询,查询时透明解压,对应用无感
Continuous Aggregates(连续聚合)
连续聚合相当于"物化视图 + 自动增量刷新",用于预计算高频访问的聚合结果:
- 定义一次聚合 SQL(如按天/按股票汇总),TimescaleDB 后台定时把新增数据增量合并进结果,而不是每次全量重算
- 业务查询直接读聚合表,避免对原始大表反复
GROUP BY,查询延迟从秒级降到毫秒级 - 通过
WITH NO DATA/REFRESH控制首次填充,通过refresh_lag/refresh_interval控制刷新滞后与频率 - 非常适合 K 线、同比环比、监控指标等"固定聚合 + 实时查询"场景
Retention Policy(数据保留策略)
保留策略用于自动清理过期数据,控制存储成本与查询性能:
- 通过
add_retention_policy为超表设定"保留窗口"(如只保留最近 2 年) - 到期 chunk 会被后台 job 自动删除,无需手写
DELETE脚本 - 可配合连续聚合:原始明细只保留短期,聚合结果长期保留,既省空间又保历史统计
Data Tiering(分层存储)
分层存储把"冷热数据"放到不同成本的存储介质上:
- 热数据(近期、频繁访问)留在本地高速 SSD
- 冷数据(历史、很少访问)自动下沉到对象存储(如 S3 / 兼容 S3 的存储),按访问透明拉取
- 在云版本(Timescale Cloud / TimescaleDB 2.13+ 的
tiered storage)中开箱即用,自托管版本需结合外部对象存储配置 - 对上层查询无感:查询历史区间时,引擎自动从对应层级读取,用户只看到一张统一的超表
TimescaleDB Docker 安装
创建 docker-compose.yml 文件,内容如下:
| |
检查运行状态:
检查是否启用了扩展:
TimescaleDB 使用
建表、转为超表
| |
查询库里已有的超表
| |
插入数据
使用 akshare 包获取股票数据(中国中车、招商银行),插入到 stock_daily 表中。Python 完整代码如下:
| |
执行如下:
查询 Chunk 信息

满足定义的按月分区。
查询数据
按月聚合数据,查询每个股票的月最高、月最低、月成交量、月成交额、平均涨跌幅。
查询中国中车(601766.SH)最近一年的 5 天数据,按涨跌幅降序排序。
查询招商银行(600036.SH)近 5 日、10 日、20 日均线。
| |
性能与使用建议
- 选好时间列:
create_hypertable的时间列应是最常用的查询过滤维度;本文用trade_date而非timestamp,契合日线场景 - chunk 不要太大也不要太小:单 chunk 建议控制在 25MB ~ 数 GB;写入密集可缩小
chunk_time_interval,查询跨度大可适当放大 - 写入用批量:如文中
execute_values(page_size=500),比单条INSERT快一个数量级 - 先压缩再保留:压缩降成本,保留控体积,二者组合是时序存储的标准套路
- 连续聚合下沉热点查询:把"固定聚合"预计算掉,明细表只做明细分析
- 善用分区裁剪:查询务必带上时间条件,否则会扫描全部 chunk 失去优势
小结
TimescaleDB 不是另起炉灶的数据库,而是把 PostgreSQL 变成一个"为时序而生"的引擎:超表 + chunk 解决分区与扩展,压缩 + 连续聚合解决成本与查询,保留 + 分层解决生命周期。对已经使用 Postgres 的团队而言,无需引入新技术栈,就能平滑获得时序数据库的能力。