时序数据库超表架构深度体验(下篇):压缩、分布式和真实战场上的表现
发布时间:2026/8/21 22:58:21 作者:尧图编辑部 阅读量:1,286
:压缩、分布式和真实战场上的表现)
文章目录压缩从GB级到百MB级的魔术数据保留策略自动清理过期数据分布式超表水平扩展的终极方案看看真实项目里的表现北京轨交TCC写入性能提升10倍机场预测性维护从被动抢修到预判未来性能数据不只看写入峰值写在最后兼容是对前人努力的尊重是确保业务平稳过渡的基石然而这仅仅是故事的起点上篇把超表的核心架构、二维分区和查询机制聊了一遍。这篇接着往下走说说压缩、数据保留策略、分布式超表以及几个真正在生产环境里跑着的落地案例。说实话上篇写完之后我自己又看了一遍感觉架构层面的东西讲得差不多了但很多人关心的实际用起来到底怎么样这个问题还没回答。压缩比能到多少数据量上来之后性能扛不扛得住真到了几千台设备并发写入的场景系统表现如何下篇就是补这些的。压缩从GB级到百MB级的魔术时序数据有个特点——相邻时间点的数据值变化通常不大。温度传感器前一秒读25.3度下一秒大概率还是25度出头。振动值、电流值也差不多都是在一定范围内缓慢波动。如果用传统行存储来存每个值都得用完整的8字节DOUBLE PRECISION来存。一天下来一个设备的一个指标可能就是几十KB的数据。但你有一万台设备、每台设备几十个指标呢乘起来就是个不小的数字了。再乘以365天呢金仓的超表压缩就是针对这个问题设计的。从使用手册里看压缩的原理是这样的开启压缩之后多行数据会被压缩成单行——没错真的是把很多行数据塞进一行里。它以矩阵的方式组织数据一列一列地存而不是像原来那样一行一行地存。手册里给了个很直观的例子。假设你有个表存了这些原始数据时间 | 设备ID | 设备类型 | CPU使用率 12:00:01 | A | SSD | 70.11 12:00:01 | B | HDD | 69.70 12:00:02 | A | SSD | 70.12 12:00:02 | B | HDD | 69.69 12:00:03 | A | SSD | 70.14 12:00:03 | B | HDD | 69.70压缩之后就变成了这样时间 | 设备ID | 设备类型 | CPU使用率 [12:00:01~12:00:03的所有时间] | [A,B,A,B,A,B] | [SSD,HDD,SSD,HDD,SSD,HDD] | [70.11,69.70,70.12,69.69,70.14,69.70]6行变成了1行。当然这只是个示意实际的压缩算法比这复杂得多。使用手册里提到了几种压缩算法Delta-of-Delta增量编码专门处理时间戳这种递增序列、Gorilla浮点数压缩处理温度、压力这种变化不大的浮点数、RLE游程编码处理重复值多的列、字典编码处理设备类型这种取值有限的列。系统会根据不同数据类型自动匹配合适的压缩方式。多模融合有个数据压缩可以减少约90%的存储空间占用。北京轨交TCC项目的实际效果也是存储空间降低了70%到80%。怎么用呢配置起来也不复杂-- 第一步设置压缩参数ALTERTABLEdevice_metricsSET(timescaledb.compress,timescaledb.compress_segmentbydevice_id,timescaledb.compress_orderbytime DESC);-- 第二步添加自动压缩策略7天前的数据自动压缩SELECTadd_compression_policy(device_metrics,INTERVAL7 days);这里有两个关键参数要说一下compress_segmentby决定压缩数据按什么字段分段。一般设成device_id这样同一个设备的数据在一起压缩。为什么因为查询的时候你大概率会按设备来查——某设备过去一周的温度曲线这种。如果按设备分段压缩了查某个设备的数据时就只需要解压这个设备对应的段不用解压整个Chunk。compress_orderby决定压缩段内的排序方式。通常按时间排序因为时序数据按时间访问是最常见的模式。手动压缩也可以做比如你想立即压缩某个Chunk-- 手动压缩指定超表中7天前的数据块SELECTcompress_chunk(chunk)FROMshow_chunks(device_metrics,older_thanINTERVAL7 days)ASchunk;已经压缩的数据如果需要修改得先解压-- 解压某个块SELECTdecompress_chunk(chunk)FROMshow_chunks(device_metrics,older_thanINTERVAL7 days)ASchunk;数据保留策略自动清理过期数据时序数据有个特殊性——它有保质期。但如果手动去删又怕删错了或者忘了删。超表提供了自动数据保留策略-- 超过180天的数据自动删除SELECTadd_retention_policy(device_metrics,INTERVAL180 days);设完之后系统会在后台定期检查到了时间窗口之外的Chunk整个被DROP掉。注意是整块删除不是一条一条DELETE所以速度非常快也不会产生大量WAL日志。结合连续聚合一起用效果更好。你可以这样做原始数据保留30天按小时聚合的连续聚合视图保留1年按天聚合的连续聚合视图永久保留这样近期数据有高精度远期数据有趋势概览存储成本也可控。-- 创建保留策略SELECTadd_retention_policy(device_metrics,INTERVAL30 days);-- 对连续聚合视图也设置保留策略SELECTadd_retention_policy(hourly_temp_stats,INTERVAL365 days);SELECTadd_retention_policy(daily_temp_stats,INTERVAL1000 days);冷热分层也是个值得说的点。金仓的方案不是简单粗暴地把老数据删了而是可以把旧数据迁移到低成本的存储上。使用手册里提到了move_chunk和attach_tablespace这些函数可以把历史Chunk搬到更便宜的表空间里。查询的时候这些冷数据照样可以查只是IO性能会稍微差一点。不过冷数据本来就很少被查这点差异可以接受。分布式超表水平扩展的终极方案前面说的这些都是单机场景下的能力。但有些场景单机的能力确实不够用。比如金仓那份组件介绍里提到的船舶安全监管平台——50万终端、每天1.2亿条GPS数据、5个分片节点、百TB级存储规模。这种量级的数据靠一台机器再强也撑不住。这时候就需要分布式超表了。分布式超表的思路是把数据分散到多个数据节点上每个节点负责一部分数据。从应用层看你还是一张超表INSERT和SELECT的写法跟单机版完全一样。但底下数据实际上分布在不同节点上并行处理。使用手册里说创建分布式超表需要先配置数据节点-- 添加数据节点SELECTadd_data_node(dn1,hostnode1.example.com);SELECTadd_data_node(dn2,hostnode2.example.com);SELECTadd_data_node(dn3,hostnode3.example.com);-- 创建分布式超表SELECTcreate_distributed_hypertable(device_metrics,time,partition_number3,replication_factor1);分布式超表支持数据分片和多副本。partition_number控制分片数replication_factor控制副本数。副本数大于1时数据会有多份副本分布在不同节点上某个节点挂了数据也不会丢。使用手册里提到的高可用设计是基于物理日志的全同步复制数据不丢失。备节点支持异步复制不阻塞事务。节点故障恢复后自动回归保持集群规模稳定。具体的数据路由是系统自动处理的。你往分布式超表里INSERT一条数据系统根据时间戳和空间哈希算出这条数据应该去哪个节点然后自动路由过去。查询的时候也是系统知道哪些数据在哪些节点上并行地去各个节点取数据然后汇总返回。工业时序中有一个关键设计访问节点侧通过智能元数据路由算法先将排序、聚合、分组等算子下发至数据节点让计算尽量放到数据所在位置处理。很多时序查询并不需要回传全部明细数据比如按分钟统计平均温度、按小时计算最大电流。先在本地完成局部计算再汇总结果可以最大化减少数据跨节点搬运。这个设计在分布式场景下尤其重要。如果每次查询都要把所有节点的原始数据拉到中心节点再计算网络开销会非常大。把计算推到数据端只传回聚合结果效率高得多。看看真实项目里的表现光说架构设计不够有说服力来看几个真正在生产环境里跑着的案例。北京轨交TCC写入性能提升10倍北京轨道交通应急指挥调度平台每天要处理的数据包括列车实时位置、速度、牵引能耗、信号设备状态、车站客流密度、环境温湿度每秒数十万条时序数据点。旧系统用的是传统关系型数据库。用了几年之后问题越来越严重早晚高峰写入队列堆积监控大屏延迟从亚秒劣化到十几秒运营分析报表跑一次要等好几个小时。换到金仓时序数据库之后技术团队上了一主多从的读写分离集群。主节点专门负责高频写入多个从节点承担监控大屏和后台分析查询。写入和查询在物理上完全隔离互不干扰。实际效果写入性能比旧系统提升超过10倍存储空间占用降低70%到80%“某线路过去一个月早高峰的列车平均旅行速度分析”从分钟级降到秒级系统已稳定存储TB级全网时序历史数据可扩展到百TB级热数据、温数据、冷数据分层存储兼顾查询性能和存储成本机场预测性维护从被动抢修到预判未来这个案例的标题就很有意思——“被动抢修再见”。机场的设备维护以前是坏了再修这种模式效率低不说更威胁运行安全。你想想飞机相关的设备哪个敢等它坏了再去想怎么办但反过来说过度维护也浪费钱——设备明明还好好的就按固定周期去检修人力物力都是消耗。金仓时序数据库在这个场景里做的事情是通过对设备运行数据的持续采集和时序分析在故障真正发生之前就识别出异常趋势触发预警。这个能力的基础就是超表对海量历史设备数据的快速检索和聚合能力。设备传感器每秒上报的温度、振动、电流等数据通过超表高效写入和存储。然后用时间桶聚合做不同时间粒度的分析发现设备性能的退化趋势。当某个指标的走势偏离正常范围的时候系统自动预警。AI要做精准判断需要很多上下文温度变化曲线、振动和电流是否同步异常、设备近期的检修记录、同类机型的历史故障。这些数据在传统架构里散落在不同系统中数据工程师光做对齐和搭管道就得花掉项目大半时间。在融合架构里时序数据、关系数据、空间数据甚至向量数据都在同一个库里一条SQL就能关联查询AI团队可以把精力放到模型本身。性能数据不只看写入峰值最后说几个性能相关的数据。金仓官方的组件介绍里有一组TSBSTime Series Benchmark Suite基准测试结果测试环境是96 vCPU、512GB内存、1TB块存储。写入方面设备规模小的时候比如100台设备10个指标InfluxDB性能更好。但设备规模一大4000台以上金仓就开始反超了。到1000万设备的规模金仓的写入性能是InfluxDB的2.67倍。这个规律其实好理解。小数据量下InfluxDB作为专用时序库有天然优势。但数据规模大了之后金仓的分区策略和并行写入能力开始发挥作用规模效应就体现出来了。查询方面的差距更大。简单查询两者表现差不多但复杂查询场景下金仓的优势非常明显——有些场景性能差了2倍到70倍不等。写在最后我对金仓时序数据库超表架构的整体感受是这样的它不是一个单点技术的突破而是一套系统性的解决方案。超表把分片管理从人工运维变成了内核自动化。二维分区把时间轴和空间轴结合起来既控制了数据块规模又分散了写入压力。压缩和数据保留策略把存储成本打下来了。连续聚合让常用分析结果随取随用。分布式超表提供了水平扩展的上限。而从架构选择的角度看金仓走的是融合路线——把时序能力长在KingbaseES这个成熟的关系型数据库内核上而不是另起炉灶做一个独立的时序库。这意味着标准SQL、ACID事务、与关系数据和空间数据的无缝关联这些能力都是天然具备的。至于适不适合你的场景这个得具体看。但我觉得至少值得认真了解一下——特别是如果你正在被传统分区表的运维复杂度折磨得头大的话。好了就写到这吧。有什么想讨论的欢迎留言。