小 T 导读:在拓斯达的智能工厂整体解决方案项目中,传统的关系型数据库已经无法高效处理时序数据,在加载、存储和查询等多个方面都遇到了挑战,最终他们选择了 TDengine 来匹配工业传感器数据的应用分析场景。本文将讲述他们应用 TDengine 的具体实践。
企业简介
广东拓斯达科技股份有限公司(简称:拓斯达,股票代码:300607)是广东省首家登陆创业板的机器人骨干企业。拓斯达坚持“让工业制造更美好”的企业使命,通过以工业机器人、注塑机、CNC为核心的智能装备,以及控制、伺服、视觉三大核心技术,打造以核心技术驱动的智能硬件平台,为制造企业提供智能工厂整体解决方案。
项目介绍
在工业领域, 生产、测试、运行阶段都可能会产生大量带有时间戳的传感器数据,这都属于典型的时序数据。时序数据主要由各类型实时监测、检查与分析设备所采集或产生,涉及制造、电力、化工、工程作业等多个行业,具备写多读少、量非常大等典型特性。
在我们的业务中,传统的关系型数据库(Relational Database)已经无法高效处理时序数据,在加载、存储和查询等多个方面都遇到了挑战。主要问题可以汇总如下:
- 写入吞吐低:单机写入吞吐量低,很难满足时序数据千万级的写入压力;
- 存储成本大:在对时序数据进行压缩时性能不佳,需占用大量机器资源;
- 维护成本高:单机系统,需要在上层人工进行分库分表,维护成本高;
- 查询性能差:海量实时数据的聚合分析性能差。
为了更好地满足时序数据的处理需求,我们决定进行数据库选型调研,最终选择了时序数据库(Time-Series Database)TDengine。 事实证明,TDengine 针对时序数据的写入、存储、索引、查询等方面都进行了特定的优化,从而实现了更优的数据加载、数据压缩、查询写入性能,非常匹配工业传感器数据的应用分析场景。
选择 TDengine 的理由
与通用数据库相比,TDengine 的压缩率表现惊人,核心原因是其采用列式存储,而且采用了二阶段压缩策略,还针对不同数据类型采取了不同的压缩算法,这种压缩机制使其压缩率远超其他数据库。
此外 TDengine 还拥有极高的读写性能,并且读写速度受数据存储规模的影响微乎其微,要知道通用数据库的数据量一旦过百万级,读写速度就会有明显下降,之前我们做过一次 MySQL 批量插入数据的测试,性能差距明显,这也是在大量级数据存储下我们会选择TDengine的重要原因之一。具体来说,TDengine 优势如下:
- 数据的读写速度快且自带时间戳,使用 SQL 进行数据库操作,简单易学,支持复杂查询
- 数据压缩率高,大量级的数据也不会占据过多存储空间,可导出数据进行备份
- 拥有交流社区和交流群,遇见问题可以和 TDengine 的其他使用者一起探讨,而且官方的同学也能提供及时的帮助
当然,世上没有完美的数据库,我们在应用之后总结出了两点待改进的地方:
- 无法使用可视化软件如 Navicat 等进行数据库操作(TDengine GUI)
- 目前还没有 Windows 版的服务端,像我们上一个客户,只在本地 Windows 上使用程序,在没有安装虚拟机和部署到服务器的情况下,就无法部署 TDengine
但每一款产品都是在发现问题和改进问题的步伐中逐渐进步的,而且对于我们的业务实现来说,TDengine 不存在明显的短板。没有最优的数据库,在场景匹配的情况下,我们最终采用了 TDengine。
落地实践
- 平台架构
我们是通过网关采集设备数据推送到 MQTT,Java 后端监听到后会写入 TDengine,在后端按需求查询处理后再把数据返回给前端。
具体来说,网关会先读取后台发布的上行规则,在采集到设备数据后,使用上行规则对数据进行处理计算后再将结果返回给下行规则模块,后台监听到后,会连接 TDengine 进行数据库表的创建修改和数据写入。之前在云平台我们使用过 Kafka 进行数据的发布订阅,现在所有环境都改为 MQTT 了。
- 超级表及建模思路
在应用 TDengine 时,我们建立了流水数据库 “iot_platform” 用来存储网关传来的数据,便于日后查询使用。我们遵循“一个采集点一张表,一类数据一个超级表”的思路来建表,在具体实践上设计了两张超级表,一张是用于存储 log 指令内容的“logs”表,另一张是用于存储其它指令内容的“datas”表,数据类型基本为电流电压、设备状态等。在进行数据存储时首先会对数据加以判断,再决定将数据存储到哪张表里。
落地效果
运行一段时间后,TDengine 的查询、写入速度完全可以满足我们目前的客户需求,最慢的分钟级,最快的能达到 1 秒一条;一个设备一天最多能写入近十万条数据,近千个设备同时写入也完全没有问题,相较于之前,写入速度提升了数十倍。查询数据在以月为单位的时间范围内没有过于明显的延迟,整体的数据压缩比大概是1/10,目前每天产生的数据量在数G左右。
- 流水数据查询
查询某一时间段内的流水数据,使用查询语句:
SELECT datagettime as ts , ${dataName} as data FROM ${tableName}
<where>
uuid = ${uuid}
<if test="startTime != null ">
and datagettime > #{startTime}
</if>
<if test="endTime != null ">
and #{endTime} > datagettime
</if>
and ${dataName} is not null
</where>
limit 0, ${countLimit}
- 聚合函数计算一天的数据
使用 TDengine 的函数计算每天的用电量,再通过每天的去计算月和年数据,查询语句为:
select diff(${dataName}) as data
from ${tableName}
where ${dataName} > 0
and datagettime > #{startTime}
and #{endTime} >= datagettime
- 计算某一时间段内的数据
select ${method}(${dataName}) as data
from ${tableName}
where uuid = ${uuid}
and datagettime > #{startTime}
and #{endTime} > datagettime;
写在最后
在工业互联网快速发展的大背景下,工业生产现场投放了大量的设备传感器和监控系统,二者提供的实时数据能够反映设备的状态和生产的进度,其中的大多数据都是按照时间顺序形成的实时数据,这些海量实时数据有着多样化的分析需求和重要的参考价值。
未来希望 TDengine 可以提供更复杂的流式计算、查询分析以及监测预警等能力,可以为产品的可视化运维、预测性维护、远程智能管理等方面提供数据依据,从而降低人员、时间等成本,加速工业化与信息化的深度融合,促进复杂重型装备制造业的转型升级,产生社会经济效益。