小 T 导读:在使用 TDengine 的时候,通过官网的技术文档可以学习到建库(database)、建表(table)的各种 SQL 语句,但是一旦要跟自己的具体业务场景结合,经验不足的朋友可能会不知道到底如何下手,本文将分享一些常见的建模方式,希望帮助大家更好地落地 TDengine。
不同于 OpenTSDB、Prometheus 等时序数据库(Time-Series Database),TDengine 允许一个表有多个列(即每条记录中,多个采集量共用一个时间戳的存储方式),这样在建表时可以有更大的灵活性。
智能电表是个典型的可以按照设备建表,多列存储时序数据的例子。但在实际使用过程中,情况可能会更复杂,一定要结合本身数据的情况来灵活设计表结构。
按照设备建表,在官网文档中已经有详细的例子和介绍,本文除了介绍一个设备一张表的建模方式外,还会对另外几种建模方式做一个补充。
1、按照设备建表的标准情形
上文中的智能电表例子就是一个设备一张表的标准情形。这种标准情形有以下特点:
(1) 相同类型的设备,采集指标完全相同。(比如上文例子中的智能电表,只采集电流、电压、相位三个指标)
(2) 就同一个设备而言,各采集指标同时采集,采集时间戳相同。
(3) 就同一个设备而言,各采集指标每次采集的数据最好是在同一个消息中上报到 TDengine,而非分别上报。
这种情况的处理最简单:
-
采用多列模式,即为每个类型的设备创建一张多列超级表。
-
为该类型的每个设备创建一张子表。
-
子表从第二列起,每一列均为一个采集指标。
图一:TDengine database 表设计
以智能电表为例:
图二:一个采集点一张表
图三:超级表使用实例
2、按照设备建表,但同类型设备的采集指标不完全相同
实际生产中,同类型的设备有时候采集指标也不完全相同,这种情况下有以下特点:
(1) 相同类型的设备,采集指标大体相同,但每个设备可能有少量个性化的指标。(前提:所有个性化指标总数加上共有指标总数不超过 1024 个,2.1.7.0 版本后总数为不超过 4096 个)
(2) 就同一个设备而言,各采集指标同时采集,采集时间戳相同。
(3) 就同一个设备而言,各采集指标每次采集的数据在同一个消息中上报到 TDengine,而非分别上报。
这种情况类似于 1,但区别是每个设备可能有个性化的采集指标。针对这种情形的处理思路常称为“大宽表”:
-
创建一个多列超级表,包含所有不同的采集指标列,为所有采集指标的全集。
-
为每个设备创建一张子表。
-
子表从第二列起,每一列均为一个采集指标。
-
数据写入时,对于该设备不具备的采集指标填入 null 值。
图示和图三接近,不同处在于建立超级表时,采集指标需要按照最多的设备去处理。
3、按照采集指标建表-1
更复杂的场景中,设备的固定表结构很难抽象出来,或者表结构经常改变,无法固定,此时需要有更灵活的处理思路。以下任一个特点满足时,需考虑按指标建表的思路:
(1) 相同类型的设备,采集指标无法固定,或者每个设备有大量个性化的指标。(前提:所有个性化指标总数加上共有指标总数超过 1024,2.1.7.0 版本后为指标总数超过 4096 个)
(2) 就同一个设备而言,各采集指标有各自的采集时间戳。(即同一个设备的不同采集指标的采集时间、采集周期等无法保证相同)
(3) 就同一个设备而言,各采集指标每次采集的数据分多个消息上报到 TDengine,且时间延迟无法确定。
这种情形要求更高的灵活性。一般处理思路如下:
-
创建单列的超级表,即时间戳+采集值,而在标签项中增加采集指标 ID 这一标签。
-
每个设备的每个采集指标单独创建一张表,在标签项中增加具体的采集指标 ID。
-
不同数据类型的采集指标要划归不同超级表,比如数值型、布尔型和字符串型的数据应该分别归入三类对应的超级表。
图四:单列模型建模示例
示例如下:
图五:单列模型建模实例
4、按照采集指标建表-2
此场景可能出现在工业物联网 PLC 数据采集中。
(1) 相同类型的设备,采集指标无法固定。
(2) 就同一设备而言,各采集指标有各自的采集频率,不过采集频率是确定的,比如 PLC1~PLC10 的采集频率是 10ms,PLC11~PLC20 的采集频率是 20ms。
(3) 就同一设备而言,后续可能会动态添加 PLC 通道。期望可以在不修改代码的情况下动态增加超级表的列。
(4) 希望通过一个超级表来统一管理。
建模思路:
-
创建多列的超级表,采集字段不同的数据类型各设置建立一个。即时间戳+采集值 int+采集值 double+ 采集值 nchar……,而在标签项中增加采集指标 ID 这一标签。
-
每个设备的采集指标单独创建一张表,在标签项中增加具体的采集指标 ID。
-
其中时间戳必填的列,剩余列则要根据测点类型填写,比如测点上报的是整形数据,就只需要设置time、采集值 int 这两列,其余列为 null。
示例如下:
图六:按照采集指标建模实例
以上为几种常见建模方式,覆盖了大部分的实际场景,当然实际业务中的情况是多种多样的,如果以上建模思路不能满足,也欢迎和加入 TDengine 的用户社区,我们一起交流。