一年1956亿行:智能电表场景下的时序数据存储实践

某省的智能电表采集项目里,500万个观测点按固定周期上报读数,一年攒下来将近1956亿行时序数据。项目对数据库的要求很直白:存得下、读得快、多年历史数据能快速装载。

真正做进去才发现,这三件事没一件省心。规模摆在那儿:单这一年的原始数据就要占去数TB空间;采集系统升级时,多年的历史数据要迁到新环境,业务等着上线;运维和业务要拉某块表几个月甚至一年的负荷曲线,响应慢一点儿,两边都来找你。

这篇笔记基于金仓时序数据库(KES TSDB)的落地过程整理而成,把存储压缩、历史数据装载和数据组织三个方面的实践摊开聊聊,附上实测数据和几个踩过的坑。

先看数据特征,再谈压缩

工业时序数据有个明显特点:按固定周期采集,相邻时间点的值高度相关。智能电表场景尤其如此------15分钟一个采集点,同一块表的读数不会跳变;即便有突变,大多数字段的变化也是缓慢的。重复信息占了存储的大头,直接按行存,大量空间浪费在冗余上。

针对时间序列数据特点,金仓时序数据库的存储引擎做了针对性优化,主要手段有四类:Delta-of-Delta差值编码、Gorilla XOR压缩、字典编码、列式存储。

Delta-of-Delta处理的是时间戳。固定周期采集时,相邻时间差恒定,二阶差分直接退化成常量,存储开销降到几个比特。Gorilla XOR处理数值,相邻读数接近时异或结果高位大量为0,压缩率很可观。字典编码留给状态类字段,电表通断状态、异常代码这类枚举值,存字典索引比存原文省得多。列式存储则让同列同类型的数据物理上聚在一起,前面几种编码才真正发挥出威力。

某省智能电表场景的实测:500万观测点、一年1956亿行数据,压缩比做到45:1。数TB的原始数据落到盘上只有两百GB量级,同期与业界同类方案对比,这个压缩水平约为对方的3.6倍。

压缩不是免费午餐。查询时数据要解压,CPU开销实打实;写入太密集,同批数据的局部性也会打折扣。我们的取舍是冷数据全量压缩,热数据保留近线窗口,查询密集的时段优先保延迟。

历史数据装载:701分钟,465万行/秒

系统升级、数据迁移、数据平台建设以及智能分析应用落地,都会撞上同一个问题:多年积累的历史数据要在业务窗口期内装完。

TB级数据用常规导入方式并不划算。常规写入路径是为在线事务设计的,批量装载反而处处受限:单条语句的解析、提交、索引维护一样都省不掉,1956亿行这个量级,几天几夜都跑不完。

金仓时序数据库面向时序场景优化了历史数据快速插入能力:批量组织写入单元、按分区并行落盘、压缩与索引分开走,把顺序写发挥到极致。

分布式部署环境下的测试结果:1956亿行历史数据,701分钟装载完成,平均写入速度465万行/秒,约为业界同类方案的2.3倍以上。原本要跑两三天的迁移任务,一个业务白天就能做完,业务等待时间短了一大截。

数据组织:时序超表和手工分区表的差距

500万观测点、多级标签(区域、台区、电表型号),数据怎么组织直接决定查询快慢。

金仓时序数据库提供时序超表机制:按时间自动分区,空间维度(设备、标签)做内部分片,分区生命周期交给数据库自己管。早期的方案是手工建分区表,按月、按台区拆,DDL和维护脚本越写越多,后来每加一个维度都要动一批历史分区,改造成本越来越高。

同等数据规模、同等表结构条件下,两种方案的对比测试:

测试场景 时序超表 普通分区表
实时插入 404秒 549秒
曲线查询 253毫秒 4834毫秒

插入快了约四分之一,曲线查询快了19.1倍。查询差距主要来自分区裁剪:曲线查询带上了设备ID和时间范围,超表能直接定位到对应分区和分片,扫描量小一个量级;分区表在大范围时间查询时裁剪粒度不足,扫进去大量无效数据块。

几个值得记下的坑

时钟漂移躲不掉。部分老电表时钟不准,上报时间乱序,入库时按设备维度做了时间线校正,否则分区会被打得碎片化。

迟到数据要单独照顾。补报的数据跨了分区,写入走了独立的late-data路径,避免和实时流抢锁。

稀疏观测点比想象中多。不是每个点每期都有数,空值处理方式直接影响压缩率,后来补了空值压缩标记,才把压缩比稳住在45:1。

小结

时序数据库的价值,"能存"只是起点,存完之后管不管得动才见分晓。1956亿行这个量级上,压缩决定成本,装载决定工期,组织方式决定查询体验。这三件事我们还在持续打磨,尤其是压缩策略与查询延迟的平衡,随着业务查询越来越复杂,要调的地方还不少。

相关推荐
Shirley~~1 小时前
从0搭建一个3D立体场景:光影与交互全解析
前端·3d
迪康coolmu1 小时前
迪康Defender网络准入控制系统落地实战:部署、配置与问题排查记录
运维·开发语言·网络·经验分享·php
兰亭妙微UI设计公司1 小时前
兰亭妙微分享:高手设计登录页的12种切入点
开发语言·前端·javascript
前端Baymax1 小时前
静默的 86 小时:全链 402 停摆与零告警的故障复盘
开发语言·前端·javascript
要开心吖ZSH1 小时前
定时任务从外部调度搬回本地 @Scheduled:一次连接池被打满的复盘与选型思考
前端·firefox
不停喝水1 小时前
【前端转全栈java速通课】 项目实战④12-14节 拦截器过滤器和全局配置-cors跨域设置-token体系-利用session做验证码
java·开发语言·前端·ai·容器
小白鸽i1 小时前
【linux】麒麟桌面版安装人大金仓V8
linux·运维
代码猎人1 小时前
怎么开发一个微信小程序
前端
虎鲸不是鱼1 小时前
AI 自动化逆向(五)控制组:区分「没有」和「没取到」
人工智能·自动化·大模型·ai逆向·ai反编译