我们将遥测数据的 ETL 流程迁移至 TimescaleDB 后,针对单表 2000万行 数据进行了查询性能对比。TimescaleDB 使用的硬件配置低于 MySQL 服务器。
查询特定日期的数据分布(分组聚合):
SELECT station_name, count(*) as dd
FROM dms_data_gzdy
WHERE date(record_time)='2025-09-18'
GROUP BY station_name
ORDER BY dd DESC
LIMIT 10;
耗时:17360 ms
扫描方式:全表扫描 + 行级计算
耗时:2475 ms
提升幅度:约 7-8 倍
这不仅仅是“索引”的区别,而是存储架构的代差。本次测试中 TimescaleDB 开启了 segmentby='switch_oid' 压缩特性,带来了三重加速机制。
| 技术特性 | MySQL (传统行存) | TimescaleDB (列式压缩) |
|---|---|---|
| 1. 数据过滤 (Pruning) |
全表扫描 (Full Scan) 由于使用了 date() 函数,MySQL 无法利用时间索引,必须取出2000万行数据,逐行计算日期函数后比对。 |
块级剪枝 (Chunk Exclusion) TimescaleDB 自动按时间分片。查询时直接根据元数据排除所有非 9月18日 的物理文件,I/O 开销极小。 |
| 2. 存储格式 (Storage) |
行式存储 (Row-oriented) 即使只查两个字段,也必须把整行数据(包含电压、电流等无关字段)从磁盘读入内存,I/O 浪费严重。 |
列式存储 (Columnar) 压缩模式下转为列存。只读取 record_time 和 station_name 对应的压缩块,无需读取无关列。 |
| 3. 聚合计算 (Grouping) |
内存排序 (Shuffle & Sort) 数据按写入时间乱序存储, GROUP BY 需要在内存中重新排序、分组计算,消耗大量 CPU。 |
物理预聚簇 (Pre-clustered) 由于配置了按设备ID ( segmentby) 压缩,数据在物理磁盘上已经是按设备分好组的。查询时无需排序,直接获取聚合结果。 |
🔍 大海捞针
“把图书馆里 2000 万本书全部搬到桌子上,一本本翻开封面,用计算器算一下出版日期是不是今天,是的话再统计。”
⚡ 精准直达
“直接走到‘2025年9月’的书架(时间分片),拿出只写着书名的目录卡片(列存),发现卡片已经按出版社排好序了(Segment By),直接数一下就行。”