从理论到实践:如何用 TDengine 打造完美数据模型​

在用 TDengine 进行数据建模之前,我们需要回答两个关键问题:建模的目标用户是谁?他们的具体需求是什么?在一个典型的时序数据管理方案中,数据采集和数据应用是两个主要环节。如下图所示:

对于数据采集工程师而言,他们的主要需求是简单、高效地收集数据。为此,可以考虑创建一个贴源层,该层的数据模型建议与数据源完全一致。这种方式能够大大简化数据采集的过程,使得数据采集工作更加轻松和直观。参见上图贴源层。

另一方面,对于数据应用开发工程师来说,他们需要处理不同业务部门的需求。这些工程师希望数据能够按照业务主题分类,并能够按照预期的访问方式来建模。为了满足这一需求,需要在数据模型中考虑访问层的设计,使得数据应用更加便捷。参见上图访问层。

显然,在数据采集和数据应用之间存在着巨大的鸿沟,那我们如何才能完成时序数据从采集到应用的转换?这就需要引入数据分层的思想。具体来说,可以在贴源层和访问层之间增加一个整合层,用于完成时序数据的时间戳对齐、关联整合、数据汇聚和数据转换等功能。这一整合层的引入,能够实现从数据采集到数据应用的无缝转换,满足不同阶段的需求。

本篇文章将从时序数据采集和应用面临的挑战及需求出发,为大家分析 TDengine 数据建模的原理与方法,并通过实际案例帮助读者更好地理解和应用这些概念。

时序数据的采集和应用开发

采集面临的挑战

对于时序数据采集工程师来说,面临的挑战主要是数据源的格式、数据传输方式、采集入库后的数据模型,在贴源层与采集源的模型按照 1:1 创建方式下,数据源的格式和入库后的数据模型的格式对齐了,也就不需要担心格式不同导致的问题了。

最常见的数据传输方式有三种情况:

  • 单表多列模型:对于数据源来说,如果一个数据采集设备的所有测点,在数据上传时都是一起上传,那么,可以建立单表多列模型的超级表。也就是说,创建一个超级表,该表中包含该采集设备的所有测点指标。
  • 多表多列模型:对于数据源来说,如果一数据采集设备包含多个测点,但这些测点的采集频次并不相同,举例来说:该设备总共采集 120 个测量指标,其中前 40 个测点的采集周期是秒级、中间 40 个测点采集周期是 1 分钟级、最后 40 个测点的采集周期是 5 分钟级,那么,我们需要分别创建三个超级表,第一个超级表包含前 40 个测量值,第二个超级表包含中间 40 个测量值,第三个超级表包含最后的 40 个测量值。这就是多表多列模型,也就是说,创建多个超级表,每个超级表也包含多个列。
  • 多表单列模型:如果数据源是每个测点单独上报,并且每个测点的采集时间戳并不相同,对于这种情况,需要按照数据类型分类,采用多表单列模型。也就是说,每个超级表中只包含一个数据类型,比如 double、int、varchar 等等,每种数据类型一个超级表。子表按照数据类型+设备类型来创建,让子表的数量保持在合理的规模,这样能够利用多个 Vnode来保障性能。

应用开发面临的挑战

对于时序数据应用开发的工程师来说,时序数据能否按照业务主题划分、能否支持实时查询和批量查询等业务场景,这些因素都十分关键。如下图所示:

  • 按照主题划分:以卷烟厂为例,卷烟厂包括多个车间如制丝和卷包,对应的业务应用往往有制丝集控、卷包数采等等。如果我们将这些业务应用按照业务主题划分,分别进行数据建模就能够极大地方便应用开发。各个业务主题共享数据整合层的数据,整合层的数据来源于贴源层,是经过时间戳对齐、数据关联整合、数据汇聚的。
  • 支持实时查询:对于时序数据来说,实时监控是非常典型的业务场景,TDengine 提供了缓存、流计算和数据订阅三种方式,供应用层实时访问。
    • 缓存:对于实时监控场景,TDengine 提供了缓存功能,在创建数据库时,可以通过设置 CACHEMODEL 参数,让 TDengine 在内存中缓存各个子表的最新数据。对于业务应用来说,可以通过 last_row/last,从缓存中实时读取设备的最新状态。
    • 流计算:TDengine 的流式计算引擎提供了实时处理写入数据流的能力,使用 SQL 定义实时数据流的转换规则,当数据被写入流的源表后,数据会被以指定的方式自动处理,并根据指定的触发模式向目标表推送计算结果。它提供了替代复杂流处理系统的轻量级解决方案,并且,能够在高吞吐的数据写入的情况下,将流计算的延迟控制在毫秒级。
    • 数据订阅:除了上述的流计算,TDengine 还提供了类似 Kafka 的数据订阅功能,帮助应用实时获取写入 TDengine 的数据,或者以事件到达顺序处理数据。TDengine 的 topic 有三种,可以是数据库、超级表、或者一个 SELECT 语句。这种方式提供了更大的灵活性,数据的颗粒度可以随时调整,而且数据的过滤与预处理交给 TDengine,有效地减少传输的数据量,并且,降低了应用开发的复杂度。
  • 支持批量查询:对于批量时序数据查询场景,TDengine 提供了 SQL 接口给上层应用查询批量数据使用。也提供了诸多时序数据窗口函数,包括计数窗口(count window)、时间窗口(time window)、状态窗口(status window)、会话窗口(session window)、事件窗口(event window)等多种窗口。
    • taosx:除了通过 SQL 查询之外,对于数据量比较大,需要通过文件或数据库接口同步数据的场景,还可以考虑使用 taosx 来同步数据。

数据建模原理和方法

数据建模原理

TDengine 数据建模的核心原理只有一个:

让查询直接定位到数据块。

首先,我们来观察一下 TDengine 是如何将规模很大的数据切分成很多个数据块的。TDengine 分别从采集点维度和时间戳维度对大规模数据进行分片(Sharding)分区(Partition),如下图所示

对于数据建模来说,我们要充分利用分片(Sharding)分区(Partition)

这两大维度对数据进行切分,确保在查询时,我们的过滤条件(Where 子句)能够直接定位某个、或者某几个数据块,数据块的个数越少越好。定位到的数据块越少,说明过滤的越高效,所需要的磁盘IO带宽越小,查询速度也越快。

数据建模基本概念

请参见:
https://docs.taosdata.com/concept/。

智能电表是典型的时序数据场景。假设每个智能电表采集电流、电压、相位三个量,有多个智能电表,每个电表有位置 Location 和 type 的静态属性。其采集的数据类似如下的表格:

每一条记录都有设备 ID、时间戳、采集的物理量(如上表中的 current、voltage 和 phase)以及每个设备相关的静态标签(location 和 type)。

  • 数据采集点(Data Collection Point):数据采集点是指按照预设时间周期或受事件触发采集物理量的硬件或软件。智能电表示例中的 d1001、d1002、d1003、d1004 等就是数据采集点。为充分利用其数据的时序性和其他数据特点,TDengine 采取一个数据采集点一张表的策略,按照此策略,上述 d1001、d1002、d1003、d1004 分别建表。
  • 标签(Label/Tag):标签是指传感器、设备或其他类型采集点的静态属性,不随时间变化。比如设备型号、颜色、设备的所在地等。
  • 采集量(Metric):采集量是指传感器、设备或其他类型采集点采集的物理量。比如电流、电压、温度、压力、GPS 位置等,是随时间变化的。数据类型可以是整型、浮点型、布尔型,也可是字符串。

创建超级表

为智能电表这个设备类型建立一个超级表,采集量有电流、电压和相位,标签有位置和类型。

创建子表

用 smeter 做模板,为 6 个智能电表创建 6 张表,地理位置标签为北京朝阳、海淀、上海浦东等。

聚合查询

查询北京朝阳区所有智能电表的电压平均值和电流最大值。

多维分析

查询北京地区所有类型为 1 的智能电表的电压平均值。

TDengine 数据建模优势

TDengine 数据建模的优势包括:

  • 超级表可以向普通表一样查询,但可以指定标签的过滤条件
  • 标签可以多至 128 个,每个标签代表一个维度
  • 标签可以事后增加、删除、修改。这样数据建模时,可以先不确定标签或分析维度
  • 每个标签,可以是一树状结构,比如“北京·朝阳·望京”,这样便于缩小搜索范围

数据建模案例

以新能源充电站建模场景为例。

背景信息

该客户管理一些充电站:

  • 充电站管理的充电桩大约有几百个,每个充电桩每天可能多次进行充电
  • 每次充电产生一个充电订单,充电订单每年大约有 1000 万个,数据需要保留 2 年
  • 需要监控充电过程中电压、电流等信息,对于历史订单能够回放充电过程
  • 数据查询方式:按照订单查询,期望能够实时监控正在充电的订单、以及能够查询历史订单充电过程

数据建模思考

常规思维,按照一个采集点一张表的原则,这里显然会按照充电桩来创建子表。但是,这样一来存在一个问题,我们按照订单查询时就无法直接定位到某个或者某几个数据块。按照充电桩来创建子表,数据的确会按照充电桩进行分片(Sharding),并且,分片后的数据也按照时间戳进行了分区(Partition),但是,业务查询的时候未指定时间戳范围,而是查询指定的 order_id,所以,无法定位到具体的数据块,需要在分片中进行全量数据扫描,必然导致性能十分低下。如下图所示:

正确的建模思路

让我们回顾 TDengine 数据建模原理:

让查询直接定位到数据块。

业务希望按照订单来查询,那么,我们直接按照订单来对数据进行分片(Sharding),

也就是说每个订单创建一张子表。这样,按照订单查询时,我们能够直接定位到该分片,这样的好处是查询的性能非常好,也非常方便,但也存在两个问题:

  • 每年新建 1000 万张子表,订单数据保留 2 年,预计就有 2000 万张子表,规模会不会太大?
  • 数据保留周期是 2 年,对于超过 2 年的子表,是否能够自动删除呢?

幸运的是,对于时序数据领域常见的“高基数”问题,TDengine 已经很好地解决了,2000 万张子表对于关系型数据库来说,可能是天文数字,但是,对于 TDengine 来说就是小菜一碟。

对于超过 2 年的子表,TDengine 提供了 TTL(Time to Live),是用来指定表的生命周期(单位:天)。如果创建表时指定了这个参数,当该表的存在时间超过 TTL 指定的时间后,TDengine 将自动删除该表。

实际数据建模

  • 创建超级表

  • 为单个订单创建子表(假设订单号:801234567),保留 2 年到期自动删除

  • 按照充电订单查询

通过对时序数据采集和应用的挑战及需求的分析,本文深入探讨了 TDengine 数据建模的原理与方法。我们不仅揭示了数据建模的核心概念和技术细节,还通过实际案例展示了其在新能源场景下的应用效果。希望读者能从中获得启发,在实际工作中灵活运用 TDengine 数据建模的方法,提高时序数据管理的效率与质量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/49062.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python中的__new__方法及实现单例模式

在Python中,类的实例化过程通常由两个主要方法控制:__new__和__init__。虽然我们大多数时候只需要关注__init__方法,但__new__方法在某些高级用例中非常有用。本文将详细介绍__new__方法,解释其定义、使用场景以及与__init__方法的…

EXCEL怎么自动添加表格吗?

第一步&#xff0c;选中需要添加表格的范围 第二步&#xff0c;点击开始&#xff0c;选择条件格式&#xff0c;“使用公式确定要设置格式的单元格” 第三步&#xff0c;编辑规则说明加上<>"" 第四步&#xff0c;点击边框&#xff0c;选择外边框确定即可&#x…

matlab 中的methods(Access = protected) 是什么意思

gpt版本 在 MATLAB 中&#xff0c;methods 是用于定义类方法的一部分。(Access protected) 是一种访问控制修饰符&#xff0c;它限制了方法的访问权限。具体来说&#xff0c;当你在类定义中使用 methods(Access protected) 时&#xff0c;你是在定义只有类本身及其子类可以访…

bash 笔记

这一篇的内容&#xff0c;太乱了。以后再整理: 把熟悉的内容删掉。不熟悉的内容放到前面。 # bash: export HOME$PWD export PS1"$" 更简短把 home 把当前目录设置为 home, 目的是缩短命令提示符前面的内容。 看起来更简短。zcat labevents.csv.gz | awk -F, (…

电脑没有摄像头怎么用手机当摄像头?虚拟摄像头使用的详细教程来了(全)

随着科技水平以及全球化经济的快速发展&#xff0c;视频会议、在线课程和直播已经成为日常办公或者生活中必不可少的一个环节。然而&#xff0c;在如今仍有许多台式电脑和一些老旧的笔记本电脑并没有内置摄像头&#xff0c;亦或者自带的摄像头质量不够理想&#xff0c;这使得视…

1小时上手Alibaba Sentinel流控安全组件

微服务的雪崩效应 假如我们开发了一套分布式应用系统&#xff0c;前端应用分别向A/H/I/P四个服务发起调用请求&#xff1a; 但随着时间推移&#xff0c;假如服务 I 因为优化问题&#xff0c;导致需要 20 秒才能返回响应&#xff0c;这就必然会导致20秒内该请求线程会一直处于阻…

跟代码执行流程,读Megatron源码(四)megatron训练脚本initialize.py之initialize_megatron()分布式环境初始化

在前文中&#xff0c;我们讲述了pretrain函数的执行流程&#xff0c;其首要步骤是megatron分组的初始化与环境的配置。本文将深入initialize_megatron函数源码&#xff0c;剖析其初始化分布式训练环境的内部机制。 注&#xff1a;在此假设读者具备3D并行相关知识 一. initiali…

引入缓存带来的问题以及解决方案

目录 前言 问题与解决方案 缓存击穿 缓存穿透 缓存雪崩 缓存一致性 前言 在提升接口性能的方案中&#xff0c;毫无疑问&#xff0c;使用缓存是最有效果的&#xff0c;但同时也会带来新的问题。 缓存击穿缓存穿透缓存雪崩缓存一致性 以上问题都是引入缓存需要考虑的&am…

react入门到实战-day2-7.21

昨天晚上刚学完已经一点了&#xff0c;来不及写笔记&#xff0c;主要是想睡觉哈&#xff0c;所以今天补上&#xff0c;我发现效率还挺高的&#xff0c;今天重新做笔记&#xff0c;加固了昨天的知识点&#xff0c;要不以后都这样子哈&#xff0c;学完第二天再写哈&#xff0c;要…

【Linux】从零开始认识多线程 --- 线程ID

在这个浮躁的时代 只有自律的人才能脱颖而出 -- 《觉醒年代》 1 前言 上一篇文章中讲解了线程控制的基本接口&#xff1a; 线程创建pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);: pthread_t *thread :输出…

OpenCV分水岭算法watershed函数的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 描述 我们将学会使用基于标记的分水岭算法来进行图像分割。我们将看到&#xff1a;watershed()函数的用法。 任何灰度图像都可以被视为一个地形表…

【数据结构_C语言】归并排序—文件类型

文章目录 1.排序定义2. 代码实现 1.排序定义 内排序&#xff1a;数据量相对少一些&#xff0c;可以放到内存中排序。 外排序&#xff1a;数据量较大&#xff0c;内存中放不下&#xff0c;数据放到磁盘文件中&#xff0c;需要排序。 归并排序&#xff1a; 2. 代码实现 void…

Flask 框架 redirect() url_for()

url_for url_for 函数根据传入的端点名称&#xff08;即路由函数名&#xff09;生成对应的 URL。 1. url_for() url_for 函数根据传入的端点名称&#xff08;即路由函数名&#xff09;生成对应的 URL。 它接受一个或多个参数&#xff0c;其中第一个参数是路由的名称&#x…

编写DockerFile

将自己的项目或者环境通过Docker部署到服务器需要一下几个步骤&#xff1a; 打包项目或者环境 编写Dockerfile文件 运行Dockerfile文件&#xff0c;构建DockerImages镜像&#xff0c;将DockerImages存入DockerHub或者存入阿里云镜像仓库 服务器pull下DockerImages镜像&#…

挖掘基于边缘无线协同感知的低功耗物联网 (LPIOT) 的巨大潜力

关键词&#xff1a;边缘无线协同感知、低功耗物联网(LPIOT)、无线混合组网、用电监测、用电计量、多角色、计量插座、无线场景感知、多角色运用、后台边缘层&#xff0c;网络边缘层&#xff0c;场景能效管理&#xff0c;场景能耗计算 在数字化和智能化日益加速的今天&#xff…

科普文:重读并翻译分布式计算经典文论-MapReduce

MapReduce计算模型于2003年提出于google&#xff0c;并迅速在google内部被广泛运用在各个领域&#xff0c;因为google存在许多基于大型数据的计算问题&#xff0c;而刚好MapReduce能够同时利用上千台机器进行分布式并行计算。MapRedue易于使用&#xff0c;由于它把并行化、分布…

甄选范文“论面向方面的编程技术及其应”,软考高级论文,系统架构设计师论文

论文真题 针对应用开发所面临的规模不断扩大、复杂度不断提升的问题,面向方面的编程(Aspect Oriented Programming,AOP)技术提供了一种有效的程序开发方法。为了理解和完成一个复杂的程序,通常要把程序进行功能划分和封装。一般系统中的某些通用功能,如安全性、持续性、日…

C++ —— STL简介

1. 什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的 组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架 2.STL的版本 原始版本 Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本…

深度学习优化:Mojo模型中自定义特征的稀疏表示处理

深度学习优化&#xff1a;Mojo模型中自定义特征的稀疏表示处理 在机器学习领域&#xff0c;特征的稀疏表示是一种常见的数据表示方式&#xff0c;尤其在处理文本、图像和网络数据时。Mojo模型&#xff0c;作为模型部署的一种形式&#xff0c;支持将训练好的模型转换为可在不同…

【Java】中的List集合

目录 一、什么是List集合二、List的常用方法List的初始化元素操作1.添加元素2.删除元素3.修改元素4.查询元素 三、List集合的遍历1.for循环遍历2.增强for循环3.迭代器遍历 一、什么是List集合 List集合是最常用的一种数据结构之一。它具有动态扩容、元素添加、删除和查询等基础…