doc: refactor document -- part one

This commit is contained in:
gccgdb1234 2024-07-19 14:08:54 +08:00
parent d6f8d79223
commit 2dc543bde3
40 changed files with 2030 additions and 857 deletions

138
docs/zh/02-concept/index.md Normal file
View File

@ -0,0 +1,138 @@
---
sidebar_label: 时序数据基础
title: 时序数据基础
description: 时序数据基础概念
toc_max_heading_level: 4
---
## 什么是时序数据?
时序数据即时间序列数据Time-Series Data它们是一组按照时间发生先后顺序进行排列的序列数据。日常生活中设备、传感器采集的数据就是时序数据证券交易的记录也是时序数据。因此时序数据的处理并不陌生特别在是工业自动化以及证券金融行业专业的时序数据处理软件早已存在比如工业领域的 PI System 以及金融行业的 KDB。
这些时序数据是周期、准周期产生的,或事件触发产生的,有的采集频率高,有的采集频率低。一般被发送至服务器中进行汇总并进行实时分析和处理,对系统的运行做出实时监测或预警,对股市行情进行预测。这些数据也可以被长期保存下来,用以进行离线数据分析。比如统计时间区间内设备的运行节奏与产出,分析如何进一步优化配置来提升生产效率;统计一段时间内生产过程中的成本分布,分析如何降低生产成本;统计一段时间内的设备异常值,结合业务分析潜在的安全隐患,以降低故障时长等等。
过去的二十年,随着数据通讯成本的急剧下降,以及各种传感技术和智能设备的出现,特别是物联网与工业 4.0 的推动,工业、物联网企业为了监测设备、环境、生产线及整个系统的运行状态,在各个关键点都配有传感器,采集各种数据。从手环、共享出行、智能电表、环境监测设备到电梯、数控机床、挖掘机、工业生产线等都在源源不断的产生海量的实时数据,时序数据的体量正指数级的增长。以智能电表为例,智能电表每隔 15 分钟采集一次数据,每天会自动生成 96 条记录。现在全中国已经有超过 10 亿台智能电表,一天就产生 960 亿条时序数据。一台联网的汽车往往每隔 10 到 15 秒采集一次数据发到云端,那么一天下来就很容易产生 1000 条记录。假设中国有 2 亿车辆联网,它们每天将产生总计 2000 亿条甚至更多的时序数据。
由于数据量指数级的增长,而且对分析和实时计算的需求越来越多,特别是在人工智能的时代,传统的时序数据处理工具难以满足需求,对每天高达 10TB 级别的海量时序大数据如何进行实时的存储、分析和计算,成为一个技术挑战,因此海量时序大数据的高效处理在过去的十年获得全球工业界的高度关注。
## 时序数据的十大特征
相对于普通的互联网的应用数据,时序数据有着很多明显的特征。涛思数据的创始人陶建辉先生早在 2017 年,就对此进行了充分地归纳分析,总结了时序数据本身以及时序数据应用的十大特征:
1. 数据是时序的,一定带有时间戳:联网的设备按照设定的周期,或受外部的事件触发,源源不断地产生数据,每条记录都是在一个时间点产生的,其时间戳必须记录,否则记录的值没有任何意义。
2. 数据是结构化的:物联网、工业设备产生的数据以及证券交易数据往往是结构化的,而且绝大多数都是数值型的,比如智能电表采集的电流、电压就可以用 4 字节的标准的浮点数来表示。
3. 一个数据采集点就是一个数据流:一个设备采集的数据、以及一支股票的交易数据,与另外一个设备采集的数据或股票是完全独立的。一台设备的数据一定是这台设备产生的,不可能是人工或其他设备产生的。一台设备产生的数据或一支股票的交易数据只有一个生产者,也就是说数据源是唯一的。
4. 数据较少有更新删除操作:对于一个典型的信息化或互联网应用,记录可能是经常需要修改或删除的。但对于设备或交易产生的数据正常情况下不会去更新/删除。
5. 数据不依赖于事务:在设备产生的数据中,具体的单条数据价值相对不高,数据的完整性和一致性并不像传统关系型数据库那样严格,大家关心的是趋势,所以不需要引入复杂的事务机制。
6. 相对互联网应用,写多读少:对于互联网应用,一条数据记录,往往是一次写,很多次读。比如一条微博或一篇微信公共号文章,一次写,但有可能上百万人读。但工业、物联网设备产生的数据不一样,一般是计算、分析程序自动读,且次数不多,只有遇到事故、人们才会主动读取原始数据。
7. 用户关注的是一段时间的趋势:对于一条银行交易记录,或者一条微博、微信,对于它的用户而言,每一条都很重要。但对于物联网、工业时序数据,每个数据点与数据点的变化并不大,大家关心的更多是一段时间,比如过去五分钟、一小时数据变化的趋势,不会只针对一个时间点进行。
8. 数据是有保留期限的:采集的数据一般都有基于时长的保留策略,比如仅仅保留一天、一周、一个月、一年甚至更长时间,该类数据的价值往往是由时间段决定的,因此对于不在重要时间段内的数据,都是可以被视为过期数据整块删除的。
9. 需要实时分析计算操作:对于大部分互联网大数据应用,更多的是离线分析,即使有实时分析,但要求并不高。比如用户画像、可以积累一定的用户行为数据后进行,早一天晚一天画不会特别影响结果。但是对于工业、物联网的平台应用以及交易系统,对数据的实时计算要求就往往很高,因为需要根据计算结果进行实时报警、监控,从而避免事故的发生、决策时机的错过。
10. 流量平稳、可预测:给定工业、物联网设备数量、数据采集频次,就可以较为准确的估算出所需要的带宽、流量、存储等数字,以及每天新生成的数据大小。而不是像电商,在双 11 期间,淘宝、天猫、京东等流量是几十倍的涨幅。也不像 12306 网站,春节期间,网站流量是几十倍的增长。
上述的特征使时序数据的处理具有着独特的需求和挑战。但是反过来说,对于一个高效的时序数据处理平台,它也必然充分利用这十大特征来提升它的处理能力。
## 时序数据的典型应用场景
时序数据应用的细分场景有很多,这里简单列举一些
1. 电力能源领域:电力能源领域范围较大,不论是在发电、输电、配电、用电还是其他环节中,各种电力设备都会产生大量时序数据,以风力发电为例,风电机作为大型设备,拥有可能高达数百的数据采集点,因此每日所产生的时序数据量极其之大,对这些数据的监控分析是确保发电环节准确无误的必要工作。在用电环节,对智能电表实时采集回来的电流、电压等数据进行快速计算,实时了解最新的用电总量、尖、峰、平、谷用电量,判断设备是否正常工作。有些时候,电力系统可能需要拉取历史上某一年的全量数据,通过机器学习等技术分析用户的用电习惯、进行负荷预测、节能方案设计、帮助电力公司合理规划电力的供应。或者拉取上个月的尖峰平谷用电量,根据不同价位进行周期性的电费结算,以上都是时序数据在电力能源领域的典型应用。
2. 车联网/轨道交通领域:车辆的 GPS 、速度、油耗、故障信息等,都是典型的时序数据,通过对它们科学合理地数据分析,可以为车辆管理和优化提供强有力的支持。但是,不同车型采集的点位信息从数百点到数千点之间不一而同,随着联网的交通设备数量越来越多,这些海量的时序数据如何安全上传、数据存储、查询和分析,成为了一个亟待解决的行业问题。对于交通工具的本身,科学合理地处理时序数据可以实现车辆轨迹追踪、无人驾驶、故障预警等功能。对于交通工具的整体配套服务,也可以提供良好的支持。比如,在新一代的智能地铁管理系统中,通过地铁站中各种传感器的时序数据采集分析,可以在站中实时展示各个车厢的拥挤度、温度、舒适度等数据,让用户可以自行选择体验度最佳的出行方案,对于地铁运营商,也可以更好地实现乘客流量的调度管理。
3. 智能制造领域:过去的十几年间,许多传统工业企业的数字化得到了长足的发展,单个工厂从传统的几千个数据采集点,到如今数十万点、上百万点,部分远程运维场景面临上万设备、千万点的数据采集存储的需求,这些数据都属于典型的时序数据。就整个工业大数据系统而言,时序数据的处理是相当复杂的。以烟草行业的数据采集为例,设备的工业数据协议各式各样、数据采集单位随着设备类型的不同而不同。数据的实时处理能力随着数据采集点的持续增加而难以跟上,与此同时还要兼顾数据的高性能、高可用、可拓展性等等诸多特性。但从另一个角度来看,如果大数据平台能够解决以上困难,满足企业对于时序数据存储分析的需求,就可以帮助企业实现更加智能化、自动化的生产模式,从而完成质的飞升。
4. 智慧油田:智慧油田也称为数字油田或智能油田,是指利用先进的信息技术和装备,实现油气田层析图和动态生产数据实时更新,提升油气田的开发效率和经济效益的一种油田开发模式。在长期的建设和探索中,钻井、录井、测井、开发生产等勘探开发业务,产生了来自油井、水井、气井等数十种设备的大量时序数据。为了实现统一以油气生产指挥中心为核心的油气生产信息化智能管控模式,满足科学高效智能的油气生产管理需求。该系统需要确保油田几万口油气水井、阀组、加热炉等设备的实时数据处理,做到高效的写入和查询、节省存储空间、基于业务灵活水平扩展、系统简单易用、数据安全可靠。更有一些大型的智慧油田项目,还会把全国各个地区的油田的生产数据实时同步汇总到总部的云端平台,依靠“边云协同”的方式完成“数据入湖”的统一筹划管理模式。
5. IT 运维领域IT 领域中,基础设施(如服务器、网络设备、存储设备)、应用程序运行的过程中会产生大量的时序数据。通过对这些时序数据的监控,可以很快地发现基础设施/应用的运行状态和服务可用性,包括系统是否在线、服务是否正常响应等;也能看到具体到某一个具体的点位的性能指标:如 CPU 利用率、内存利用率、磁盘空间利用率、网络带宽利用率等; 还可以监控系统产生的错误日志和异常事件,包括入侵检测、安全事件日志、权限控制等,最终通过设置报警规则,及时通知管理员或运维人员具体的情况,从而及时发现问题、预防故障,并优化系统性能,确保系统稳定可靠地运行。
6. 金融领域:金融领域目前正经历着数据管理的一场革命,它们的行情数据属于典型的时序数据,由于保留行情数据的储存期限往往需长达 5 至 10 年,甚至超过 30 年,而且可能全世界各个国家/地区的主流金融市场的交易数据都需要全量保存,因此行情数据的总量数据体量庞大,会轻松达到 TB 级别,造成存储、查询等等各方面的瓶颈。在金融领域中,量化交易平台是最能凸显时序数据处理重要性的革命性应用之一:通过对大量时序行情数据的读取分析来及时响应市场变化,帮助交易者把握投资机会,同时规避不必要的风险,实现资产的稳健增长。可以实现包括但不限于:资产管理、情绪监控、股票回测、交易信号模拟、报表自动生成等等诸多功能。
## 处理时序数据所需要的工具
如果想要高效地处理时序数据,一个完整的时序数据处理平台一定要准备好以下几个核心模块。
1. 数据库Database数据库提供时序数据的高效存储和读取能力。在工业、物联网场景由设备所产生的时序数据量是十分惊人的。从存储数据的角度来说数据库需要把这些数据持久化到硬盘上并最大程度地压缩从而降低存储成本。从读取数据的角度来说数据库需要保证实时查询以及历史数据的查询效率。比较传统的存储方案是使用 MySql、Oracle 等关系型数据库,也有 Hadoop 体系的 HBase专用的时序数据库则有 InfluxDB、OpenTSDB、Prometheus 等。
2. 数据订阅Data Subscription很多时序数据应用都需要在第一时间订阅到业务所需的实时数据从而及时了解被监测对对象的最新状态用 AI 或其他工具做实时的数据分析。同时,由于数据的隐私以及安全,你只能容许应用订阅他有权限访问的数据。因此,一个时序数据处理平台一定需要具备数据订阅的能力,帮助应用实时获取最新数据。
3. ETLExtract Transform Load在实际的物联网、工业场景中时序数据的采集需要特定的 ETL 工具进行数据的提取、清洗和转换操作,才能把数据写入数据库中,以保证数据的质量。因为不同数据采集系统往往使用不同的标准,比如采集的温度的物理单位不一致,有的用摄氏度,有的用华氏度;系统之间所在的时区不一致,要进行转换;时间分辨率也可能不统一,因此这些从不同系统汇聚来的数据需要进行转换才能写入数据库。
4. 流计算Stream computing物联网、工业、金融应用需要对时序数据流进行高效快速计算通过所得到的计算结果来满足实时业务的需求。比如面对实时采集到的每个智能电表的电流和电压数据需要立刻算出各个电表的有功功率、无功功率。因此时序数据处理平台通常会选择一些比如 Apache Spark、Apache Flink 等等的流处理框架。
5. 缓存Cache物联网、工业、金融应用需要实时展示一些设备或股票的最新状态因此平台需要缓存技术提供快速的数据访问。原因是由于时序数据体量极大如果不使用缓存技术而是进行常规的读取、筛选那么对于监控设备最新状态之类的计算是十分困难的将会导致很大的延迟从而失去“实时”的意义。因此缓存技术是时序数据处理平台不可缺少的一环 Redis 就是这样一种常用的缓存工具。
处理时序数据需要一系列模块的协同作业,从数据采集到存储、计算、分析与可视化,再到专用的时序数据算法库,每个环节都有相应的工具支持。这些工具的选择取决于具体的业务需求和数据特点,合理地选用和搭配它们才能做到高效地处理各种类型的时序数据,挖掘数据背后的价值。
## 专用时序数据处理工具的必要性
在时序数据的十大特征一节中提到,对于一个优秀的时序大数据处理平台来说,它必然需要具备处理时序数据十大特征的能力。在处理时序数据所需要的工具一节中介绍了时序大数据平台处理时序数据所需要的主要模块/组件。 结合这两节的内容与实际情况,可以发现:处理海量时序数据,其实是一个很庞大复杂的系统。
早些年,为处理日益增长的互联网数据,众多的工具开始出现,最流行的便是 Hadoop 体系。除使用大家所熟悉的 Hadoop 组件如 HDFS、MapReduce、HBase 和 Hive 外,通用的大数据处理平台往往还使用 Kafka 或其他消息队列工具Redis 或其他缓存软件Flink 或其他实时流式数据处理软件。存储上也有人选用 MongoDB、Cassandra 或其他 NoSQL 数据库。这样一个典型的大数据处理平台基本上能很好的处理互联网行业的引用,比如典型的用户画像、舆情分析等。
因此很自然,在工业、物联网大数据兴起后,大家仍然想到的是使用这套通用的大数据处理平台来处理时序数据。现在市场上流行的物联网、车联网等大数据平台几乎无一例外是这类架构,这套方法被证明完全可以工作,但效果仍然有很多不足:
1. 开发效率低:因为不是单一软件,需要集成至少 4 个以上模块,而且很多模块都不是标准的 POSIX 或 SQL 接口,都有自己的开发工具、开发语言、配置,需要一定的学习成本。而且由于数据从一个模块流动到另外一个模块,数据一致性容易受到破坏。同时,这些模块基本上都是开源软件,难免遇到各种 BUG即使有技术论坛、社区的支持一旦被一技术问题卡住总要耗费工程师不少时间。总的来讲需要搭建一个还不错的团队才能将这些模块顺利的组装起来因此需要耗费较大的人力资源。
2. 运行效率低:现有的这些开源软件主要用来处理互联网上的非结构化数据,比如文本、视频、图片数据等,但是通过物联网采集来的数据都是时序的、结构化的。用非结构化数据处理技术来处理结构化数据,无论是存储还是计算,消费的资源都大很多。
3. 运维成本高:每个模块,无论是 Kafka、HBase、HDFS 还是 Redis都有自己的管理后台都需要单独管理。在传统的信息系统中数据库管理员只要学会管理 MySQL 或是 Oracle 就可以了,但现在数据库管理员需要学会管理、配置、优化很多模块,工作量大了很多。由于模块数过多,定位一个问题就变得更为复杂。比如,用户发现有一条采集的数据丢失了,至于是 Kafka、HBase、Spark 丢失的,还是应用程序丢失的,则无法迅速定位,往往需要花很长时间,只有将各模块的日志关联起来才能找到原因。而且模块越多,系统整体的稳定性就越低。
4. 产品推出慢、利润低:由于源软件研发效率低,运维成本高,导致将产品推向市场的时间变长,让企业丧失商机。而且这些开源软件都在演化中,要同步使用最新的版本也需要耗费一定的人力。除互联网头部公司外,中小型公司在通用大数据平台上花费的人力资源成本一般都远超过专业公司的产品或服务费用。
5. 对于小数据量场景,私有化部署太重:在物联网、车联网场景中,因为涉及到生产经营数据的安全,很多还是采取私有化部署。而每个私有化部署,处理的数据量有很大的区别,从几百台联网设备到数千万台设备不等。对于数据量小的场景,通用的大数据解决方案就显得过于臃肿,投入产出不成正比。因此有的平台提供商往往有两套方案,一套针对大数据场景,使用通用的大数据平台,一套针对小数据规模场景,就使用 MySQL 或其他数据库来搞定一切,但是随着历史数据的累积,或接入设备量的增长,关系型数据库性能不足、运维复杂、扩展性差等缺点都会逐渐暴露出来,终究不是长久之计。
由于存在这些根本性的缺陷,导致高速增长的时序大数据市场一直没有一个简单好用而又高效的工具。于是,近些年一批专注时序数据处理的企业杀入了这个赛道,比如美国的 InfluxData其产品 InfluxDB 在 IT 运维监测方面有相当的市场占有率。开源社区也十分活跃,比如基于 HBase 开发的 OpenTSDB中国国内阿里、百度、华为都有基于 OpenTSDB 的产品,涛思数据不依赖任何第三方,推出了自主研发而且开源的的 TDengine。
由于数据量巨大且应用方式特殊,对时序数据的处理具有相当大的技术挑战,因此要使用专业的大数据平台。对实时时序数据的科学合理地高效处理能够帮助企业实时监控生产与经营过程,对历史时序数据的分析有助于对资源的使用和生产配置做出科学的决策。
## 选择时序数据处理工具的标准
毫无疑问,我们需要一个优秀的时序大数据平台来处理设备、交易产生的海量数据。那么,这个大数据平台需要具备哪些能力?与通用的大数据平台相比,它需要具备什么样的特征呢?
1. 必须是分布式系统:首先,由工业、物联网设备产生的海量数据,是任何一台单独的服务器都无能力处理的,因此处理系统必须是可分布式的、水平扩展的。这个平台在设计层面就必须能够高效地处理高基数难题:以智能电表为例,每个设备都有自己的设备 ID、城市 ID、厂商 ID 和模型 ID 等标签。几百个城市,百万级设备,再加上不同的厂商、模型。相乘之下,基数轻松超过百亿级。假如想找到某一个设备的数据,需要在百亿级的基数中筛选过滤,难度可想而知,这便是时序数据领域经典的“高基数”难题。即便是很多中小型项目,过亿的基数也是十分常见的。所以,对于时序数据工具的选型,一定要看它的架构模型能否撑得起你的业务基数。一个能够通过分布式的架构来处理“高基数”难题,才能让平台足以支撑业务的增长,才可以说是一个真正意义上的时序大数据平台。
2. 必须是高性能:“高性能”是一个相对的概念,它描述的是一款产品与其他产品相比而来的性能表现。不同大数据平台的硬件规模和需求都是不一致的,但是一个好的大数据平台绝对不应该依赖于“大硬件”,而是应该拥有强悍的单点工作能力,用更少的资源达到更好的性能,这样才是真正的做到“降本”和“增效”。如果专用的时序大数据处理平台不能在存储、读取、分析这些方面做到“高性能”,那么为什么不采用通用的大数据平台呢?
3. 必须是满足实时计算的系统:互联网大数据处理,大家所熟悉的场景是用户画像、推荐系统、舆情分析等等,这些场景并不需要什么实时性,批处理即可。但是对于物联网场景,需要基于采集的数据做实时预警、决策,延时要控制在秒级以内。如果计算没有实时性,物联网的商业价值就大打折扣。
4. 必须拥有运营商级别的高可靠服务:工业、物联网系统对接的往往是生产、经营系统,如果数据处理系统宕机,直接导致停产,产生经济有损失、导致对终端消费者的服务无法正常提供。比如智能电表,如果系统出问题,直接导致的是千家万户无法正常用电。因此工业、物联网大数据系统必须是高可靠的,必须支持数据实时备份,必须支持异地容灾,必须支持软件、硬件在线升级,必须支持在线 IDC 机房迁移,否则服务一定有被中断的可能。
5. 必须拥有高效的缓存功能:绝大部分场景,都需要能快速获取设备当前状态或其他信息,用以报警、大屏展示或其他。系统需要提供一高效机制,让用户可以获取全部、或符合过滤条件的部分设备的最新状态。
6. 必须拥有实时流式计算:各种实时预警或预测已经不是简单的基于某一个阈值进行,而是需要通过将一个或多个设备产生的数据流进行实时聚合计算,不只是基于一个时间点、而是基于一个时间窗口进行计算。不仅如此,计算的需求也相当复杂,因场景而异,应容许用户自定义函数进行计算。
7. 必须支持数据订阅:与通用大数据平台比较一致,同一组数据往往有很多应用都需要,因此系统应该提供订阅功能,只要有新的数据更新,就应该实时提醒应用。由于数据隐私和安全,而且这个订阅也应该是个性化的,只能订阅有权查看的数据,比如仅仅能订阅每小时的平均功率,而不能订阅原始的电流、电压值。
8. 必须保证数据能持续稳定写入:对于联网设备产生的数据,数据流量往往是平稳的,因此数据写入所需要的资源往往是可以估算的。但是变化的是查询、分析,特别是即席查询,有可能耗费很大的系统资源,不可控。因此系统必须保证分配足够的资源以确保数据能够写入系统而不被丢失。准确的说,系统必须是一个写优先系统。
9. 必须保证实时数据和历史数据的处理合二为一:实时数据在缓存里,历史数据在持久化存储介质里,而且可能依据时长,保留在不同存储介质里。系统应该隐藏背后的存储,给用户和应用呈现的是同一个接口和界面。无论是访问新采集的数据还是十年前的老数据,除输入的时间参数不同之外,其余应该是一样的。
10. 必须支持灵活的多维度分析:对于联网设备产生的数据,需要进行各种维度的统计分析,比如从设备所处的地域进行分析,从设备的型号、供应商进行分析,从设备所使用的人员进行分析等等。而且这些维度的分析是无法事先想好的,是在实际运营过程中,根据业务发展的需求定下来的。因此时序大数据系统需要一个灵活的机制增加某个维度的分析。
11. 需要支持即席分析和查询。为提高大数据分析师的工作效率,系统应该提供一命令行工具或容许用户通过其他工具,执行 SQL 查询,而不是非要通过编程接口。查询分析的结果可以很方便的导出,再制作成各种图表。
12. 必须支持数据降频、插值、特殊函数计算等操作。原始数据的采集频次可能很高,但具体分析往往不需要对原始数据执行,而是数据降频之后。系统需要提供高效的数据降频操作。设备是很难同步的,不同设备采集数据的时间点是很难对齐的,因此分析一个特定时间点的值,往往需要插值才能解决,系统需要提供线性插值、设置固定值等多种插值策略才行。工业互联网里,除通用的统计操作之外,往往还需要支持一些特殊函数,比如时间加权平均、累计求和、差值等。
13. 必须提供灵活的数据管理策略。一个大的系统,采集的数据种类繁多,而且除采集的原始数据外,还有大量的衍生数据。这些数据各自有不同的特点,有的采集频次高,有的要求保留时间长,有的需要多个副本以保证更高的安全性,有的需要能快速访问。因此物联网大数据平台必须提供多种策略,让用户可以根据特点进行选择和配置,而且各种策略并存。
14. 必须是开放的。系统需要支持业界流行的标准 SQL提供各种语言开发接口包括 C/C++、Java、Go、Python、RESTful 等接口,也需要支持 Spark、R、Matlab 等工具,方便集成各种机器学习、人工智能算法或其他应用,让大数据处理平台能够不断扩展,而不是成为一个孤岛。
15. 必须支持异构环境。大数据平台的搭建是一个长期的工作,每个批次采购的服务器和存储设备都会不一样,系统必须支持自己可以和各种档次、配置的服务器和存储设备并存。
16. 必须支持边云协同。要有一套灵活的机制将边缘计算节点的数据上传到云端,根据具体需要,可以将原始数据,或加工计算后的数据,或仅仅符合过滤条件的数据同步到云端,而且随时可以取消,更改策略。这样才能更好的汇聚数据,统筹业务,从而做出更好的业务决策。
17. 需要统一的后台管理系统。便于查看系统运行状态、管理集群、用户、各种系统资源等,而且系统能够与第三方 IT 运维监测平台无缝集成。
18. 需要支持私有化部署。因为很多企业出于安全以及各种因素的考虑,希望采用私有化部署。而传统的企业往往没有很强的 IT 运维团队,因此在安装、部署、运维等方面需要做到简单、快捷,可维护性强。
总之,时序大数据平台应具备高效、可扩展、实时、可靠、灵活、开放、简单、易维护等特点。近年来,众多企业纷纷将时序数据从传统大数据平台或关系型数据库迁移到专用时序大数据平台,以保障海量时序数据得到快速和有效处理,支撑相关业务的持续增长。

View File

@ -1,153 +0,0 @@
---
title: 产品简介
description: 简要介绍 TDengine 的主要功能
toc_max_heading_level: 2
---
TDengine 是一款专为物联网、工业互联网等场景设计并优化的大数据平台,它能安全高效地将大量设备、数据采集器每天产生的高达 TB 甚至 PB 级的数据进行汇聚、存储、分析和分发,对业务运行状态进行实时监测、预警,提供实时的商业洞察。其核心模块是高性能、集群开源、云原生、极简的时序数据库 TDengine OSS。
本节介绍 TDengine OSS 的主要产品和功能、竞争优势、适用场景、与其他数据库的对比测试等等,让大家对 TDengine OSS 有个整体了解
## 主要功能
TDengine OSS 的主要功能如下:
1. 写入数据,支持
- [SQL 写入](../develop/insert-data/sql-writing)
- [无模式Schemaless写入](../reference/schemaless/),支持多种标准写入协议
- [InfluxDB Line 协议](../develop/insert-data/influxdb-line)
- [OpenTSDB Telnet 协议](../develop/insert-data/opentsdb-telnet)
- [OpenTSDB JSON 协议](../develop/insert-data/opentsdb-json)
- 与多种第三方工具的无缝集成,它们都可以仅通过配置而无需任何代码即可将数据写入 TDengine
- [Telegraf](../third-party/telegraf)
- [Prometheus](../third-party/prometheus)
- [StatsD](../third-party/statsd)
- [collectd](../third-party/collectd)
- [Icinga2](../third-party/icinga2)
- [TCollector](../third-party/tcollector)
- [EMQX](../third-party/emq-broker)
- [HiveMQ](../third-party/hive-mq-broker)
2. 查询数据,支持
- [标准 SQL](../taos-sql),含嵌套查询
- [时序数据特色函数](../taos-sql/function/#time-series-extensions)
- [时序数据特色查询](../taos-sql/distinguished),例如降采样、插值、累加和、时间加权平均、状态窗口、会话窗口等
- [用户自定义函数UDF](../taos-sql/udf)
3. [缓存](../develop/cache),将每张表的最后一条记录缓存起来,这样无需 Redis 就能对时序数据进行高效处理
4. [流式计算Stream Processing](../develop/stream)TDengine 不仅支持连续查询,还支持事件驱动的流式计算,这样在处理时序数据时就无需 Flink 或 Spark 这样流式计算组件
5. [数据订阅](../develop/tmq),应用程序可以订阅一张表或一组表的数据,提供与 Kafka 相同的 API而且可以指定过滤条件
6. 可视化
- 支持与 [Grafana](../third-party/grafana/) 的无缝集成
- 支持与 Google Data Studio 的无缝集成
7. 集群
- [集群部署](../deployment/),可以通过增加节点进行水平扩展以提升处理能力
- 可以通过 [Kubernetes 部署 TDengine](../deployment/k8s/)
- 通过多副本提供高可用能力
8. 管理
- [监控](../operation/monitor)运行中的 TDengine 实例
- 多种[数据导入](../operation/import)方式
- 多种[数据导出](../operation/export)方式
9. 工具
- 提供[交互式命令行程序CLI](../reference/taos-shell),便于管理集群,检查系统状态,做即席查询
- 提供压力测试工具 [taosBenchmark](../reference/taosbenchmark),用于测试 TDengine 的性能
10. 编程
- 提供各种语言的[连接器Connector](../connector): 如 [C/C++](../connector/cpp)、[Java](../connector/java)、[Go](../connector/go)、[Node.js](../connector/node)、[Rust](../connector/rust)、[Python](../connector/python)、[C#](../connector/csharp) 等
- 支持 [REST 接口](../connector/rest-api/)
更多细节功能,请阅读整个文档。
## 竞争优势
由于 TDengine 充分利用了[时序数据特点](https://www.taosdata.com/blog/2019/07/09/105.html)比如结构化、无需事务、很少删除或更新、写多读少等等因此与其他时序数据库相比TDengine 有以下特点:
- **[高性能](https://www.taosdata.com/tdengine/fast)**TDengine 是唯一一个解决了时序数据存储的高基数难题的时序数据库,支持上亿数据采集点,并在数据插入、查询和数据压缩上远胜其它时序数据库。
- **[极简时序数据平台](https://www.taosdata.com/tdengine/simplified_solution_for_time-series_data_processing)**TDengine 内建缓存、流式计算和数据订阅等功能,为时序数据的处理提供了极简的解决方案,从而大幅降低了业务系统的设计复杂度和运维成本。
- **[云原生](https://www.taosdata.com/tdengine/cloud_native_time-series_database)**通过原生的分布式设计、数据分片和分区、存算分离、RAFT 协议、Kubernetes 部署和完整的可观测性TDengine 是一款云原生时序数据库并且能够部署在公有云、私有云和混合云上。
- **[简单易用](https://www.taosdata.com/tdengine/ease_of_use)**对系统管理员来说TDengine 大幅降低了管理和维护的代价。对开发者来说, TDengine 提供了简单的接口、极简的解决方案和与第三方工具的无缝集成。对数据分析专家来说TDengine 提供了便捷的数据访问能力。
- **[分析能力](https://www.taosdata.com/tdengine/easy_data_analytics)**通过超级表、存储计算分离、分区分片、预计算和其它技术TDengine 能够高效地浏览、格式化和访问数据。
- **[核心开源](https://www.taosdata.com/tdengine/open_source_time-series_database)**TDengine 的核心代码包括集群功能全部在开源协议下公开。全球超过 140k 个运行实例GitHub Star 20k且拥有一个活跃的开发者社区。
采用 TDengine可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。表现在几个方面
1. 由于其超强性能,它能将系统所需的计算资源和存储资源大幅降低
2. 因为支持 SQL能与众多第三方软件无缝集成学习迁移成本大幅下降
3. 因为是一款极简的时序数据平台,系统复杂度、研发和运营成本大幅降低
## 技术生态
在整个时序大数据平台中TDengine 扮演的角色如下:
<figure>
![TDengine Database 技术生态图](eco_system.webp)
<center><figcaption>图 1. TDengine 技术生态图</figcaption></center>
</figure>
上图中,左侧是各种数据采集或消息队列,包括 OPC-UA、MQTT、Telegraf、也包括 Kafka他们的数据将被源源不断的写入到 TDengine。右侧则是可视化、BI 工具、组态软件、应用程序。下侧则是 TDengine 自身提供的命令行程序CLI以及可视化管理工具。
## 典型适用场景
作为一个高性能、分布式、支持 SQL 的时序数据库Time-series DatabaseTDengine 的典型适用场景包括但不限于 IoT、工业互联网、车联网、IT 运维、能源、金融证券等领域。需要指出的是TDengine 是针对时序数据场景设计的专用数据库和专用大数据处理工具因其充分利用了时序大数据的特点它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM 等通用型数据。下面本文将对适用场景做更多详细的分析。
### 数据源特点和需求
从数据源角度,设计人员可以从下面几个角度分析 TDengine 在目标应用系统里面的适用性。
| 数据源特点和需求 | 不适用 | 可能适用 | 非常适用 | 简单说明 |
| ---------------------------- | ------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| 总体数据量巨大 | | | √ | TDengine 在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。 |
| 数据输入速度偶尔或者持续巨大 | | | √ | TDengine 的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。 |
| 数据源数目巨大 | | | √ | TDengine 设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。 |
### 系统架构要求
| 系统架构要求 | 不适用 | 可能适用 | 非常适用 | 简单说明 |
| ---------------------- | ------ | -------- | -------- | ----------------------------------------------------------------------------------------------------- |
| 要求简单可靠的系统架构 | | | √ | TDengine 的系统架构非常简单可靠,自带消息队列,缓存,流式计算,监控等功能,无需集成额外的第三方产品。 |
| 要求容错和高可靠 | | | √ | TDengine 的集群功能,自动提供容错灾备等高可靠功能。 |
| 标准化规范 | | | √ | TDengine 使用标准的 SQL 语言提供主要功能,遵守标准化规范。 |
### 系统功能需求
| 系统功能需求 | 不适用 | 可能适用 | 非常适用 | 简单说明 |
| -------------------------- | ------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| 要求完整的内置数据处理算法 | | √ | | TDengine 实现了通用的数据处理算法,但是还没有做到妥善处理各行各业的所有需求,因此特殊类型的处理需求还需要在应用层面解决。 |
| 需要大量的交叉查询处理 | | √ | | 这种类型的处理更多应该用关系型数据库处理,或者应该考虑 TDengine 和关系型数据库配合实现系统功能。 |
### 系统性能需求
| 系统性能需求 | 不适用 | 可能适用 | 非常适用 | 简单说明 |
| ---------------------- | ------ | -------- | -------- | -------------------------------------------------------------------------------------------------- |
| 要求较大的总体处理能力 | | | √ | TDengine 的集群功能可以轻松地让多服务器配合达成处理能力的提升。 |
| 要求高速处理数据 | | | √ | TDengine 专门为 IoT 优化的存储和数据处理设计,一般可以让系统得到超出同类产品多倍数的处理速度提升。 |
| 要求快速处理小粒度数据 | | | √ | 这方面 TDengine 性能可以完全对标关系型和 NoSQL 型数据处理系统。 |
### 系统维护需求
| 系统维护需求 | 不适用 | 可能适用 | 非常适用 | 简单说明 |
| ---------------------- | ------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
| 要求系统可靠运行 | | | √ | TDengine 的系统架构非常稳定可靠,日常维护也简单便捷,对维护人员的要求简洁明了,最大程度上杜绝人为错误和事故。 |
| 要求运维学习成本可控 | | | √ | 同上。 |
| 要求市场有大量人才储备 | √ | | | TDengine 作为新一代产品,目前人才市场里面有经验的人员还有限。但是学习成本低,我们作为厂家也提供运维的培训和辅助服务。 |
## 与其他数据库的对比测试
- [用 InfluxDB 开源的性能测试工具对比 InfluxDB 和 TDengine](https://www.taosdata.com/blog/2020/01/13/1105.html)
- [TDengine 与 OpenTSDB 对比测试](https://www.taosdata.com/blog/2019/08/21/621.html)
- [TDengine 与 Cassandra 对比测试](https://www.taosdata.com/blog/2019/08/14/573.html)
- [TDengine VS InfluxDB ,写入性能大 PK ](https://www.taosdata.com/2021/11/05/3248.html)
- [TDengine 和 InfluxDB 查询性能对比测试报告](https://www.taosdata.com/2022/02/22/5969.html)
- [TDengine 与 InfluxDB、OpenTSDB、Cassandra、MySQL、ClickHouse 等数据库的对比测试报告](https://www.taosdata.com/downloads/TDengine_Testing_Report_cn.pdf)
## 主要产品
TDengine 有两个主要产品TDengine Enterprise (即 TDengine 企业版)和 TDengine Cloud关于它们的具体定义请参考
- [TDengine 企业版](https://www.taosdata.com/tdengine-pro)
- [TDengine 云服务](https://cloud.taosdata.com/?utm_source=menu&utm_medium=webcn)

75
docs/zh/03-intro/index.md Normal file
View File

@ -0,0 +1,75 @@
---
sidebar_label: 产品简介
title: TDengine 产品简介
toc_max_heading_level: 4
---
在 2016 年底,涛思数据创始人陶建辉先生凭借多年的技术研发经验,敏锐地捕捉到时序数据呈指数级增长的态势,发现时序大数据处理领域缺乏一个高效、开放且易于
使用的工具并意识到时序大数据的处理是一个巨大的技术挑战与商业机遇。因此在2017 年,他创办了涛思数据,并亲自主导研发了 TDengine专注于时序数据处理。至今他仍致力于此领域的研究与发展。
TDengine 作为涛思数据的旗舰产品其核心是一个高性能、分布式的时序数据库。通过集成的缓存、数据订阅、流计算和数据清洗与转换等功能TDengine 已经发展成为
一个专为物联网、工业互联网、金融和 IT 运维等关键行业量身定制的时序大数据平台。该平台能够高效地汇聚、存储、分析、计算和分发来自海量数据采集点的大规模数据流,每日处理能力可达 TB 乃至 PB 级别。借助 TDengine企业可以实现实时的业务监控和预警进而发掘出有价值的商业洞察。
自 2019 年 7 月 以 来, 涛 思 数 据 陆 续 将 TDengine 的 不 同 版 本 开 源, 包 括 单 机版2019 年 7 月、集群版2020 年 8 月以及云原生版2022 年 8 月。开源之后TDengine 迅速获得了全球开发者的关注,多次在 GitHub 网站全球趋势排行榜上位居榜首。截至编写本书时TDengine 在 GitHub 网站上已积累近 2.3 万颗星安装实例超过53 万个,覆盖 60 多个国家和地区,广泛应用于电力、石油、化工、新能源、智能制造、汽车、环境监测等行业或领域,赢得了全球开发者的广泛认可
## TDengine 产品
为满足不同用户的需求和场景,涛思数据推出 TDengine 系列产品,包括开源版 TDengine OSS、企业版 TDengine Enterprise 以及云服务 TDengine Cloud。
TDengine OSS 是一个开源的高性能时序数据库与其他时序数据库相比它的核心优势在于其集群开源、高性能和云原生架构。而且除了基础的写入、查询和存储功能外TDengine OSS 还集成了缓存、流式计算和数据订阅等高级功能,这些功能显著简化了系统设计,降低了企业的研发和运营成本。
在 TDengine OSS 的基础上,企业版 TDengine Enterprise 提供了增强的辅助功能包括数据的备份恢复、异地容灾、多级存储、视图、权限控制、安全加密、IP 白名单、支持 MQTT、OPC-UA、OPC-DA、PI、Wonderware、Kafka 等各种数据源。这些功能为企业提供了更为全面、安全、可靠和高效的时序数据管理解决方案。
此外TDengine Cloud 作为一种全托管的云服务,存储与计算分离,分开计费,为企业提供了企业级的工具和服务,彻底解决了运维难题,尤其适合中小规模的用户使用。
## TDengine 主要功能与特性
TDengine 经过特别优化,以适应时间序列数据的独特需求,引入了“一个数据采集点一张表”和“超级表”的创新数据组织策略。这些策略背后的支撑是一个革命性的存储引擎,它极大地提升了数据处理的速度和效率,无论是在数据的写入、查询还是存储方面。接下来,逐一探索 TDengine 的众多功能,帮助您全面了解这个为高效处理时间序列数据而生的大数据平台。
1. 写入数据TDengine 支持多种数据写入方式。首先,它完全兼容 SQL允许用户使用标准的 SQL 语法进行数据写入。而且 TDengine 还支持无模式Schemaless写入包括流行的 InfluxDB Line 协议、OpenTSDB 的 Telnet 和 JSON 协议这些协议的加入使得数据的导入变得更加灵活和高效。更进一步TDengine 与众多第三方工具实现了无缝集成,例如 Telegraf、Prometheus、EMQX、StatsD、collectd 和 HiveMQ 等。对于 TDengine Enterprise TDengine 还提供了 MQTT、OPC-UA、OPC-DA、PI、Wonderware Kafka 等连接器。这些工具通过简单的配置,无需一行代码,就可以将来自各种数据源的数据源源不断的写入数据库,极大地简化了数据收集和存储的过程。
2. 查询数据TDengine 提供标准的 SQL 查询语法并针对时序数据和业务的特点优化和新增了许多语法和功能例如降采样、插值、累计求和、时间加权平均、状态窗口、时间窗口、会话窗口、滑动窗口等。TDengine 还支持用户自定义函数UDF
3. 缓存TDengine 使用时间驱动缓存管理策略First-In-First-OutFIFO将最近到达的当前状态数据保存在缓存中这样便于获取任何监测对象的实时状态而无需使用 Redis 等其他缓存工具,简化系统架构和运营成本。
4. 流式计算TDengine 流式计算引擎提供了实时处理写入的数据流的能力,不仅支持连续查询,还支持事件驱动的流式计算。它提供了替代复杂流处理系统的轻量级解决方案,并能够在高吞吐的数据写入的情况下,提供毫秒级的计算结果延迟
5. 数据订阅TDengine 提供了类似 Kafka 的数据订阅功能。但用户可以通过 SQL 来灵活控制订阅的数据内容,并使用 Kafka 相同的 API 来订阅一张表、一组表、全部列或部分列、甚至整个数据库的数据。TDengine 可以替代需要集成消息队列产品的场景, 从而简化系统设计的复杂度,降低运营维护成本。
6. 可视化/BITDengine 本身不提供可视化或 BI 的功能。但通过其 RESTful API 标准的 JDBC、ODBC 接口TDengine 能够 Grafana、Google Data Studio、Power BI、Tableau 以及国产 BI 工具无缝集成。
7. 集群功能TDengine 支持集群部署,能够随着业务数据量的增长,通过增加节点线性提升系统处理能力,实现水平扩展。同时,通过多副本技术提供高可用性,并支持 Kubernetes 部署。
8. 数据迁移TDengine 提供了多种便捷的数据导入导出功能包括脚本文件导入导出、数据文件导入导出、taosdump 工具导入导出等。企业版还支持边云协同、数据同步等场景,兼容多种数据源,如 AVEVA PI System 等。
9. 编程连接器TDengine 提供不同语言的连接器,包括 C/C++、Java、Go、Node.js、Rust、Python、C#、R、PHP 等。而且 TDengine 支持 REST 接口,应用可以直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库。
10. 数据安全共享TDengine 通过数据库视图功能和权限管理,确保数据访问的安全性。数据订阅功能可将数据实时分发给应用,订阅主题可通过 SQL 定义,实现灵活精细的数据分发控制,保护数据安全和隐私
11. 编程连接器TDengine 提供了丰富的编程语言连接器,包括 C/C++、Java、Go、Node.js、Rust、Python、C#、R、PHP 等,并支持 REST ful 接口方便应用通过HTTP POST 请求操作数据库。
12. 常用工具TDengine 还提供了交互式命令行程序CLI便于管理集群、检查系统状态、做即时查询。压力测试工具 taosBenchmark用于测试 TDengine 的性能。TDengine 还提供了图形化管理界面,简化了操作和管理过程。
## TDengine 与典型时序数据库的区别
由于充分利用了时序数据特点,并采用独特创新的“一个数据采集点一张表” “超级表”的属于模型与其他时序数据库相比TDengine 拥有以下特点:
1. 高性能TDengine 通过创新的存储引擎设计,实现了数据写入和查询性能的超群,速度比通用数据库快 10 倍以上,也远超过其他时序数据库。同时,其存储空间需求仅为通用数据库的 1/10极大地提高了资源利用效率。
2. 云原生TDengine 采用原生分布式设计,充分利用云平台的优势,提供了水平扩展能力。它具备弹性、韧性和可观测性,支持 Kubernetes 部署,并可在公有云、私有云和混合云上灵活运行。
3. 极简时序数据平台TDengine 内置了消息队列、缓存、流式计算等功能,避免了应用集成 Kafka、Redis、HBase、Spark 等软件的复杂性,从而大幅降低系统的复杂度和应用开发及运营成本。
4. 强大的分析能力TDengine 不仅支持标准 SQL 查询,还为时序数据特有的分析提供了 SQL 扩展。通过超级表、存储计算分离、分区分片、预计算、UDF 等先进技术TDengine 展现出强大的数据分析能力。
5. 简单易用TDengine 安装无依赖,集群部署仅需几秒即可完成。它提供了 REST ful接口和多种编程语言的连接器与众多第三方工具无缝集成。此外命令行程序和丰富的运维工具也极大地方便了用户的管理和即时查询需求。
6. 核心开源TDengine 的核心代码包括集群功能均在开源协议下公开发布。它在GitHub 网站全球趋势排行榜上多次位居榜首显示出其受欢迎程度。同时TDengine
拥有一个活跃的开发者社区,为技术的持续发展和创新提供了有力支持。
采用 TDengine企业可以在物联网、车联网、工业互联网等典型场景中显著降低大数据平台的总拥有成本主要体现在以下几个方面
1. 高性能带来的成本节约TDengine 卓越的写入、查询和存储性能意味着系统所需的计算资源和存储资源可以大幅度减少。这不仅降低了硬件成本,还减少了能源消耗和维护费用。
2. 标准化与兼容性带来的成本效益:由于 TDengine 支持标准 SQL并与众多第三方软件实现了无缝集成用户可以轻松地将现有系统迁移到 TDengine 上,无须重写大量代码。这种标准化和兼容性大大降低了学习和迁移成本,缩短了项目周期。
3. 简化系统架构带来的成本降低作为一个极简的时序数据平台TDengine 集成了消息队列、缓存、流计算等必要功能,避免了额外集成众多其他组件的需要。这
种简化的系统架构显著降低了系统的复杂度,从而减少了研发和运营成本,提高了整体运营效率。

View File

@ -1 +0,0 @@
label: 基本概念

View File

@ -1,183 +0,0 @@
---
sidebar_label: 基本概念
title: 数据模型和基本概念
description: TDengine 的数据模型和基本概念
---
为了便于解释基本概念,便于撰写示例程序,整个 TDengine 文档以智能电表作为典型时序数据场景。假设每个智能电表采集电流、电压、相位三个量,有多个智能电表,每个电表有位置 Location 和分组 Group ID 的静态属性. 其采集的数据类似如下的表格:
<div className="center-table">
<table>
<thead>
<tr>
<th rowSpan="2">Device ID</th>
<th rowSpan="2">Timestamp</th>
<th colSpan="3">Collected Metrics</th>
<th colSpan="2">Tags</th>
</tr>
<tr>
<th>current</th>
<th>voltage</th>
<th>phase</th>
<th>location</th>
<th>groupid</th>
</tr>
</thead>
<tbody>
<tr>
<td>d1001</td>
<td>1538548685000</td>
<td>10.3</td>
<td>219</td>
<td>0.31</td>
<td>California.SanFrancisco</td>
<td>2</td>
</tr>
<tr>
<td>d1002</td>
<td>1538548684000</td>
<td>10.2</td>
<td>220</td>
<td>0.23</td>
<td>California.SanFrancisco</td>
<td>3</td>
</tr>
<tr>
<td>d1003</td>
<td>1538548686500</td>
<td>11.5</td>
<td>221</td>
<td>0.35</td>
<td>California.LosAngeles</td>
<td>3</td>
</tr>
<tr>
<td>d1004</td>
<td>1538548685500</td>
<td>13.4</td>
<td>223</td>
<td>0.29</td>
<td>California.LosAngeles</td>
<td>2</td>
</tr>
<tr>
<td>d1001</td>
<td>1538548695000</td>
<td>12.6</td>
<td>218</td>
<td>0.33</td>
<td>California.SanFrancisco</td>
<td>2</td>
</tr>
<tr>
<td>d1004</td>
<td>1538548696600</td>
<td>11.8</td>
<td>221</td>
<td>0.28</td>
<td>California.LosAngeles</td>
<td>2</td>
</tr>
<tr>
<td>d1002</td>
<td>1538548696650</td>
<td>10.3</td>
<td>218</td>
<td>0.25</td>
<td>California.SanFrancisco</td>
<td>3</td>
</tr>
<tr>
<td>d1001</td>
<td>1538548696800</td>
<td>12.3</td>
<td>221</td>
<td>0.31</td>
<td>California.SanFrancisco</td>
<td>2</td>
</tr>
</tbody>
</table>
<a name="#model_table1">表 1. 智能电表数据示例</a>
</div>
每一条记录都有设备 ID、时间戳、采集的物理量如上表中的 `current`、`voltage` 和 `phase`)以及每个设备相关的静态标签(`location` 和 `groupid`)。每个设备是受外界的触发,或按照设定的周期采集数据。采集的数据点是时序的,是一个数据流。
## 采集量Metric
采集量是指传感器、设备或其他类型采集点采集的物理量比如电流、电压、温度、压力、GPS 位置等,是随时间变化的,数据类型可以是整型、浮点型、布尔型,也可是字符串。随着时间的推移,存储的采集量的数据量越来越大。智能电表示例中的电流、电压、相位就是采集量。
## 标签Label/Tag
标签是指传感器、设备或其他类型采集点的静态属性,不是随时间变化的,比如设备型号、颜色、设备的所在地等,数据类型可以是任何类型。虽然是静态的,但 TDengine 容许用户修改、删除或增加标签值。与采集量不一样的是,随时间的推移,存储的标签的数据量不会有什么变化。智能电表示例中的 `location``groupid` 就是标签。
## 数据采集点Data Collection Point
数据采集点是指按照预设时间周期或受事件触发采集物理量的硬件或软件。一个数据采集点可以采集一个或多个采集量,**但这些采集量都是同一时刻采集的,具有相同的时间戳**。对于复杂的设备,往往有多个数据采集点,每个数据采集点采集的周期都可能不一样,而且完全独立,不同步。比如对于一台汽车,有数据采集点专门采集 GPS 位置,有数据采集点专门采集发动机状态,有数据采集点专门采集车内的环境,这样一台汽车就有三个数据采集点。智能电表示例中的 d1001、d1002、d1003、d1004 等就是数据采集点。
## 表Table
因为采集量一般是结构化数据同时为降低学习门槛TDengine 采用传统的关系型数据库模型管理数据。用户需要先创建库,然后创建表,之后才能插入或查询数据。
为充分利用其数据的时序性和其他数据特点TDengine 采取**一个数据采集点一张表**的策略,要求对每个数据采集点单独建表(比如有一千万个智能电表,就需创建一千万张表,上述表格中的 d1001d1002d1003d1004 都需单独建表),用来存储这个数据采集点所采集的时序数据。这种设计有几大优点:
1. 由于不同数据采集点产生数据的过程完全独立,每个数据采集点的数据源是唯一的,一张表也就只有一个写入者,这样就可采用无锁方式来写,写入速度就能大幅提升。
2. 对于一个数据采集点而言,其产生的数据是按照时间排序的,因此写的操作可用追加的方式实现,进一步大幅提高数据写入速度。
3. 一个数据采集点的数据是以块为单位连续存储的。如果读取一个时间段的数据,它能大幅减少随机读取操作,成数量级的提升读取和查询速度。
4. 一个数据块内部,采用列式存储,对于不同数据类型,采用不同压缩算法,而且由于一个数据采集点的采集量的变化是缓慢的,压缩率更高。
如果采用传统的方式,将多个数据采集点的数据写入一张表,由于网络延时不可控,不同数据采集点的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个数据采集点的数据是难以保证连续存储在一起的。**采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的。**
TDengine 建议用数据采集点的名字(如上表中的 d1001来做表名。每个数据采集点可能同时采集多个采集量如上表中的 `current`、`voltage` 和 `phase`),每个采集量对应一张表中的一列,数据类型可以是整型、浮点型、字符串等。除此之外,表的第一列必须是时间戳,即数据类型为 Timestamp。对采集量TDengine 将自动按照时间戳建立索引,但对采集量本身不建任何索引。数据用列式存储方式保存。
对于复杂的设备,比如汽车,它有多个数据采集点,那么就需要为一辆汽车建立多张表。
## 超级表STable
由于一个数据采集点一张表导致表的数量巨增难以管理而且应用经常需要做采集点之间的聚合操作聚合的操作也变得复杂起来。为解决这个问题TDengine 引入超级表Super Table简称为 STable的概念。
超级表是指某一特定类型的数据采集点的集合。同一类型的数据采集点,其表的结构是完全一样的,但每个表(数据采集点)的静态属性(标签)是不一样的。描述一个超级表(某一特定类型的数据采集点的集合),除需要定义采集量的表结构之外,还需要定义其标签的 Schema标签的数据类型可以是整数、浮点数、字符串、JSON标签可以有多个可以事后增加、删除或修改。如果整个系统有 N 个不同类型的数据采集点,就需要建立 N 个超级表。
在 TDengine 的设计里,**表用来代表一个具体的数据采集点,超级表用来代表一组相同类型的数据采集点集合**。智能电表示例中,我们可以创建一个超级表 `meters`.
## 子表Subtable
当为某个具体数据采集点创建表时,用户可以使用超级表的定义做模板,同时指定该具体采集点(表)的具体标签值来创建该表。**通过超级表创建的表称之为子表**。正常的表与子表的差异在于:
1. 子表就是表,因此所有正常表的 SQL 操作都可以在子表上执行。
2. 子表在正常表的基础上有扩展,它是带有静态标签的,而且这些标签可以事后增加、删除、修改,而正常的表没有。
3. 子表一定属于一张超级表,但普通表不属于任何超级表
4. 普通表无法转为子表,子表也无法转为普通表。
超级表与基于超级表建立的子表之间的关系表现在:
1. 一张超级表包含有多张子表,这些子表具有相同的采集量 Schema但带有不同的标签值。
2. 不能通过子表调整数据或标签的模式,对于超级表的数据模式修改立即对所有的子表生效。
3. 超级表只定义一个模板,自身不存储任何数据或标签信息。因此,不能向一个超级表写入数据,只能将数据写入子表中。
查询既可以在表上进行也可以在超级表上进行。针对超级表的查询TDengine 将把所有子表中的数据视为一个整体数据集进行处理会先把满足标签过滤条件的表从超级表中找出来然后再扫描这些表的时序数据进行聚合操作这样需要扫描的数据集会大幅减少从而显著提高查询的性能。本质上TDengine 通过对超级表查询的支持,实现了多个同类数据采集点的高效聚合。
TDengine 系统建议给一个数据采集点建表,需要通过超级表建表,而不是建普通表。在智能电表的示例中,我们可以通过超级表 meters 创建子表 d1001、d1002、d1003、d1004 等。
为了更好地理解采集量、标签、超级与子表的关系,可以参考下面关于智能电表数据模型的示意图。
<figure>
![智能电表数据模型示意图](./supertable.webp)
<center><figcaption>图 1. 智能电表数据模型示意图</figcaption></center>
</figure>
## 库Database
库是指一组表的集合。TDengine 容许一个运行实例有多个库,而且每个库可以配置不同的存储策略。不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能最大效率的工作TDengine 建议将不同数据特征的超级表创建在不同的库里。
一个库里,可以有一到多个超级表,但一个超级表只属于一个库。一个超级表所拥有的子表全部存在一个库里。
## FQDN & Endpoint
FQDNFully Qualified Domain Name完全限定域名是 Internet 上特定计算机或主机的完整域名。FQDN 由两部分组成:主机名和域名。例如,假设邮件服务器的 FQDN 可能是 mail.tdengine.com。主机名是 mail主机位于域名 tdengine.com 中。DNSDomain Name System负责将 FQDN 翻译成 IP是互联网应用的寻址方式。对于没有 DNS 的系统,可以通过配置 hosts 文件来解决。
TDengine 集群的每个节点是由 Endpoint 来唯一标识的Endpoint 是由 FQDN 外加 Port 组成,比如 h1.tdengine.com:6030。这样当 IP 发生变化的时候,我们依然可以使用 FQDN 来动态找到节点,不需要更改集群的任何配置。而且采用 FQDN便于内网和外网对同一个集群的统一访问。
TDengine 不建议采用直接的 IP 地址访问集群,不利于管理。不了解 FQDN 概念,请看博文[《一篇文章说清楚 TDengine 的 FQDN》](https://www.taosdata.com/blog/2020/09/11/1824.html)。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,106 @@
---
sidebar_label: 安装与启动
title: TDengine 安装与启动
description: 使用安装包和 Docker 快速体验 TDengine
toc_max_heading_level: 4
---
TDengine 的安装包含括服务端taosd、应用驱动taosc、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、命令行程序CLItaos和一些工具软件。
为了适应不同用户的操作系统偏好TDengine 在 Linux 系统上提供 tar.gz 、 Deb 和 RPM 格式安装包。此外,还支持 apt-get 方式安装,这种方式简便快捷,适合熟悉 Linux 包管理的用户。
除了 Linux 平台以外TDengine 还支持在 Windows X64 平台和 macOS X64/M1 平台上安装,扩大了其适用性,满足了跨平台的需求。
对于希望进行虚拟化安装的用户TDengine 同样提供了 Docker 镜像,使得用户可以快速搭建和体验 TDengine 环境,不需要烦琐的手动配置过程。
本节将详细指导如何在 Linux 操作系统中高效地安装和启动 TDengine 3.3.0.0 版本。同时,为了迎合不同用户的多样化需求,本节还将介绍 TDengine 在 Docker 容器中的安装和启动步骤,为用户提供更多灵活性和便利性选项。
## Linux 系统
访问 TDengine 的官方版本发布页面https://docs.taosdata.com/releases/tdengine/ ,下载 TDengine 安装包TDengine-server-3.3.0.0-Linux-x64.tar.gz 。其他类型安装包的安装方法请参考相关文档TDengine 遵循各种安装包的标准。
1. 进入到安装包所在目录,使用 tar 解压安装包
```shell
tar -zxvf TDengine-server-3.3.0.0-Linux-x64.tar.gz
```
2. 解压文件后,进入相应子目录 TDengine-server-3.3.0.0,执行其中的 install.sh 安装脚本
```shell
sudo ./install.sh
```
3. 安装后,请使用 systemctl 命令来启动 TDengine 的服务进程。
```shell
sudo systemctl start taosd
```
4. 检查服务是否正常工作:
```shell
sudo systemctl status taosd
```
5. 如果服务进程处于活动状态,则 status 指令会显示如下的相关信息:
```shell
Active: active (running)
```
6. 如果后台服务进程处于停止状态,则 status 指令会显示如下的相关信息:
```shell
Active: inactive (dead)
```
如果 TDengine 服务正常工作,那么您可以通过 TDengine 的命令行程序 taos 来访问并体验 TDengine。
如下 systemctl 命令可以帮助你管理 TDengine 服务:
```shell
1. 启动服务进程sudo systemctl start taosd
2. 停止服务进程sudo systemctl stop taosd
3. 重启服务进程sudo systemctl restart taosd
4. 查看服务状态sudo systemctl status taosd
```
**注意**
- 当执行 systemctl stop taosd 命令时TDengine 服务并不会立即终止,而是会等待必要的数据成功落盘,确保数据的完整性。在处理大量数据的情况下,这一过程可能会花费较长的时间。
- 如果操作系统不支持 systemctl可以通过手动运行 /usr/local/taos/bin/taosd 命令来启动 TDengine 服务。
## Docker
1. 测试机器如果已经安装了 Docker首先拉取最新的 TDengine 容器镜像:
```shell
docker pull tdengine/tdengine:latest
或者指定版本的容器镜像:
```shell
docker pull tdengine/tdengine:3.3.0.0
```
2. 然后只需执行下面的命令:
```shell
docker run -d -p 6030:6030 -p 6041:6041 -p 6043-6049:6043-6049 -p 6043-6049:6043-6049/udp tdengine/tdengine
```
**注意**TDengine 3.0 服务端仅使用 6030 TCP 端口。6041 为 taosAdapter 所使用提供 REST 服务端口。6043-6049 为 taosAdapter 提供第三方应用接入所使用端口,可根据需要选择是否打开。
如果需要将数据持久化到本机的某一个文件夹,则执行下边的命令:
```shell
docker run -d -v ~/data/taos/dnode/data:/var/lib/taos \
-v ~/data/taos/dnode/log:/var/log/taos \
-p 6030:6030 -p 6041:6041 -p 6043-6049:6043-6049 -p 6043-6049:6043-6049/udp tdengine/tdengine
```
3. 确定该容器已经启动并且在正常运行。
```shell
docker ps
```
4. 进入该容器并执行 bash
```shell
docker exec -it <container name bash
```
然后就可以执行相关的 Linux 命令操作和访问 TDengine。
## 故障排查
如果启动 TDengine 服务时出现异常,请查看数据库日志以获取更多信息。你也可以参考 TDengine 的官方文档中的故障排除部分,或者在 TDengine 开源社区中寻求帮助。

View File

@ -0,0 +1,35 @@
---
sidebar_label: 云服务
title: 通过 云服务 快速体验 TDengine
toc_max_heading_level: 4
---
TDengine Cloud 作为一个全托管的时序大数据云服务平台致力于让用户迅速领略TDengine 的强大功能。该平台不仅继承了 TDengine Enterprise 的核心功能特性,还充分发挥了 TDengine 的云原生优势。TDengine Cloud 以其极致的资源弹性伸缩、高可用性、容器化部署以及按需付费等特点,灵活满足各类用户需求,为用户打造高效、可靠且经济的时序大数据处理解决方案。
TDengine Cloud 大幅减轻了用户在部署、运维等方面的人力负担同时提供了全方位的企业级服务。这些服务涵盖多角色、多层次的用户管理、数据共享功能以适应各种异构网络环境。此外TDengine Cloud 还提供私有链接服务和极简的数据备份与恢复功能,确保数据安全无忧。
对于中小型企业,选择 TDengine Cloud 不仅能有效降低成本还能享受到专业的服务支持。而对于大型企业TDengine Cloud 则可作为强大的概念验证和测试平台助力加速项目的上线周期。在项目成熟后企业还可根据自身需求选择私有化部署以实现更高级别的定制化需求。综上所述TDengine Cloud 为不同规模的企业提供了灵活、高效且经济的时序大数据解决方案。
## 新用户注册
要在 TDengine Cloud 注册新用户,请遵循以下简易步骤完成注册流程:
1. 打开浏览器,访问 TDengine Cloud 的首页https://cloud.taosdata.com在右边的“注册”部分填入自己的姓名以及企业邮箱地址点击“获取验证码”按钮。
2. 检查企业邮箱,找到主题为“你的 TDengine Cloud 注册账户验证码”的邮件。从邮件内容中复制 6 位验证码,并将其粘贴到注册页面上的“验证码”输入框中。接着,点击“注册 TDengine Cloud”按钮进入客户信息补全页面。
3. 在客户信息补全页面的“手机号”输入框中输入有效的手机号码,并点击“验证”按钮完成验证。验证通过后,设置一个符合要求的密码,然后点击“继续”按钮,将进入“创建实例”部分。
## 创建实例
要在 TDengine Cloud 中创建 TDengine 实例,只须遵循以下 3 个简单步骤。
1. 第 1 步选择公共数据库。在此步骤中TDengine Cloud 提供了可供公共访问的智能电表等数据库。通过浏览和查询这些数据库,你可以立即体验 TDengine 的各种功能和高性能。你可以根据需求在此步骤启动数据库访问,或在后续使用过程中再进行启动。若不需要此步骤,可直接点击“下一步”按钮跳过。
2. 第 2 步,创建组织。在此步骤中,请输入一个具有意义的名称,代表你的公司或组织,这将有助于你和平台更好地管理云上资源。
3. 第 3 步,创建实例。在此步骤中,你需要填写实例的区域、名称、是否选择高可用选项以及计费方案等必填信息。确认无误后,点击“创建”按钮。大约等待 1min新的TDengine 实例便会创建完成。随后,你可以在控制台中对该实例进行各种操作,如查询数据、创建订阅、创建流等。
TDengine Cloud 提供多种级别的计费方案,包括入门版、基础版、标准版、专业版和旗舰版,以满足不同客户的需求。如果你觉得现有计费方案无法满足自己的特定需求,请联系 TDengine Cloud 的客户支持团队,他们将为你量身定制计费方案。注册后,你将获得一定的免费额度,以便体验服务

View File

@ -0,0 +1,46 @@
---
sidebar_label: 快速体验
title: 快速体验写入和查询
toc_max_heading_level: 4
---
## 体验写入
taosBenchmark 是一个专为测试 TDengine 性能而设计的工具它能够全面评估TDengine 在写入、查询和订阅等方面的功能表现。该工具能够模拟大量设备产生的数据,并允许用户灵活控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表数量、每张子表的数据量、写入数据的时间间隔、工作线程数量以及是否写入乱序数据等策略。
启动 TDengine 的服务,在终端中执行 taosBenchmark -y 命令,系统将自动在数据库 test 下创建一张名为 meters的超级表。这张超级表将包含 10 000 张子表,表名从 d0 到 d9999每张表包含 10,000条记录。每条记录包含 ts时间戳、current电流、voltage电压和 phase相位4个字段。时间戳范围从“2017-07-14 10:40:00 000”到“2017-07-14 10:40:09 999”。每张表还带有 location 和 groupId 两个标签其中groupId 设置为 1 到 10而 location 则设置为 California.Campbell、California.Cupertino 等城市信息。
执行该命令后,系统将迅速完成 1 亿条记录的写入过程。实际所需时间取决于硬件性能,但即便在普通 PC 服务器上,这个过程通常也只需要十几秒。
taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如表的数目、记录条数等。要查看详细的参数列表,请在终端中输入 taosBenchmark --help 命令。有关taosBenchmark 的详细使用方法,请参考 TDengine 的官方文档
## 体验查询
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
1. 查询超级表 meters 下的记录总条数
```shell
SELECT COUNT(*) FROM test.meters;
```
2. 查询 1 亿条记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
3. 查询 location = "California.SanFrancisco" 的记录总条数
```shell
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
4. 查询 groupId = 10 的所有记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
5. 对表 d1001 按每 10 秒进行平均值、最大值和最小值聚合统计
```shell
SELECT _wstart, AVG(current), MAX(voltage), MIN(phase) FROM test.d1001 INTERVAL(10s);
```
在上面的查询中使用系统提供的伪列_wstart 来给出每个窗口的开始时间。

View File

@ -0,0 +1,4 @@
---
sidebar_label: 立即开始
title: 快速体验 TDengine
---

View File

@ -0,0 +1,217 @@
---
sidebar_label: 数据模型
title: TDengine 数据模型
toc_max_heading_level: 4
---
为了清晰地阐述时序数据的基本概念,并为示例程序的编写提供便利,整个文档都将以智能电表为例,探讨时序数据的典型应用场景。设想有一种型号的智能电表,它能够采集
电流、电压和相位这 3 个模拟量。此外,每块智能电表还具有位置和分组等静态属性。这些智能电表采集的数据示例如下表所示。
|Device ID| Timestamp | Current | Voltage | Phase | Location | Group ID |
|:-------:|:---------:|:-------:|:-------:|:-----:|:--------:|:--------:|
|d1001 |1538548685000 | 10.3 | 219 | 0.31 | California.SanFrancisco |2|
|d1002 | 1538548684000 | 10.2 | 220 | 0.23 | California.SanFrancisco |3|
|d1003 | 1538548686500 | 11.5 | 221 | 0.35 | California.LosAngeles | 3 |
|d1004 | 1538548685500 | 13.4 | 223 | 0.29 | California.LosAngeles | 2 |
|d1001 | 1538548695000 | 12.6 | 218 | 0.33 | California.SanFrancisco |2|
|d1004 | 1538548696600 | 11.8 | 221 | 0.28 | California.LosAngeles | 2 |
|d1002 | 1538548696650 | 10.3 | 218 | 0.25 | California.SanFrancisco | 3 |
|d1001 | 1538548696800 | 12.3 | 221 | 0.31 | California.SanFrancisco | 2 |
上表详细展示了各设备 IDDevice ID对应的智能电表在特定时刻采集的物理量数据涵盖电流current、电压voltage和相位phase等重要信息。除了动态采集的数据以外每块智能电表还配备了一组静态标签tag例如位置location和分组 IDGroup ID等。这些设备能够根据外部触发事件或预设的周期进行数据采集确保数据的连续性和时序性从而构成一个持续更新的数据流。
## 基本概念
### 采集量
采集量是指通过各种传感器、设备或其他类型的采集点所获取的物理量如电流、电压、温度、压力、GPS 等。由于这些物理量随时间不断变化,因此采集的数据类型多
样,包括整型、浮点型、布尔型以及字符串等。随着时间的积累,存储的数据将持续增长。以智能电表为例,其中的 current电流、voltage电压和 phase相位便是典型的采集量。
### 标签
标签是指附着在传感器、设备或其他类型采集点上的静态属性这些属性不会随时间发生变化例如设备型号、颜色、设备所在地等。标签的数据类型可以是任意类型。尽管标签本身是静态的但在实际应用中用户可能需要对标签进行修改、删除或添加。与采集量不同随着时间的推移存储的标签数据量保持相对稳定不会呈现明显的增长趋势。在智能电表的示例中location位置和 Group ID分组 ID就是典型的标签。
### 数据采集点
数据采集点是指在一定的预设时间周期内或受到特定事件触发时,负责采集物理量的硬件或软件设备。一个数据采集点可以同时采集一个或多个采集量,但这些采集量都是在同一时刻获取的,并拥有相同的时间戳。对于结构复杂的设备,通常会有多个数据采集点,每个数据采集点的采集周期可能各不相同,它们之间完全独立,互不干扰。以一辆汽车为例,可能有专门的数据采集点用于采集 GPS有的数据采集点负责监控发动机状态还有的数据采集点则专注于车内环境的监测。这样一辆汽车就包含了 3个不同类型的数据采集点。在智能电表的示例中d1001、d1002、d1003、d1004 等标识符即代表了不同的数据采集点。
### 表
鉴于采集的数据通常是结构化数据为了降低用户的学习难度TDengine 采用传统的关系型数据库模型来管理数据。同时为了充分发挥时序数据的特性TDengine 采取了“一个数据采集点一张表”的设计策略,即要求为每个数据采集点单独建立一张表。例如,若有千万块智能电表,则在 TDengine 中需要创建相应数量的表。在智能电表的示例数据中,设备 ID 为 d1001 的智能电表对应着 TDengine 中的一张表,该电表采集的所有时序数据均存储于此表中。这种设计方式既保留了关系型数据库的易用性,又充分利用了时序数据的独特优势。
“一个数据采集点一张表”的设计有几大优点:
1. 由于不同数据采集点产生数据的过程完全独立,每个数据采集点的数据源是唯一的,一张表也就只有一个写入者,这样就可采用无锁方式来写数据,写入速度能大幅提升。
2. 对于一个数据采集点而言,其产生的数据是按照时间递增的,因此写的操作可用追加的方式实现,进一步大幅提高数据写入速度。
3. 一个数据采集点的数据是以块为单位连续存储的。这样,每次读取一个时间段的数据,能大幅减少随机读取操作,成数量级的提升读取和查询速度。
4. 一个数据块内部,采用列式存储,对于不同的数据类型,可以采用不同压缩算法来提高压缩率。并且,由于采集量的变化通常是缓慢的,压缩率会更高。
如果采用传统的方式,将多个数据采集点的数据写入一张表,由于网络延时不可控,不同数据采集点的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个数据采集点的数据是难以保证连续存储在一起的。采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的,,而且数据压缩率最高。
在 TDengine 中通常使用数据采集点的名称d1001来做表名每个数据采集点可以有多个采集量current、voltage、phase 等),每个采集量对应一张表的一列。采集量的数据类型可以是整型、浮点型、字符串等。
此外,表的第一列必须是时间戳,即数据类型为 Timestamp。对于每个采集量TDengine 将使用第一列时间戳建立索引,采用列式存储。对于复杂的设备,比如汽车,它有多个数据采集点,则需要为一辆汽车建立多张表。
### 超级表
采用“一个数据采集点一张表”的设计虽然有助于针对性地管理每个采集点,但随着设备数量不断增加表的数量也会急剧增加,这给数据库管理和数据分析带来了挑战。在进行跨数据采集点的聚合操作时,用户需要面对大量的表,工作变得异常繁重。
为了解决这个问题TDengine 引入超级表Super Table简称为 STable的概念。超级表是一种数据结构它能够将某一特定类型的数据采集点聚集在一起形成一张逻辑上的统一表。这些数据采集点具有相同的表结构但各自的静态属性如标签可能不同。创建超级表时除了定义采集量以外还需定义超级表的标签。一张超级表至少包含一个时间戳列、一个或多个采集量列以及一个或多个标签列。此外超级表的标签可以灵活地进行增加、修改或删除操作。
在 TDengine 中,表代表具体的数据采集点,而超级表则代表一组具有相同属性的数据采集点集合。以智能电表为例,我们可以为该类型的电表创建一张超级表,其中包含了所有智能电表的共有属性和采集量。这种设计不仅简化了表的管理,还便于进行跨数据采集点的聚合操作,从而提高数据处理的效率。
### 子表
子表是数据采集点在逻辑上的一种抽象表示,它是隶属于某张超级表的具体表。用户可以将超级表的定义作为模板,并通过指定子表的标签值来创建子表。这样,通过超级表生成的表便被称为子表。超级表与子表之间的关系主要体现在以下几个方面。
- 一张超级表包含多张子表,这些子表具有相同的表结构,但标签值各异。
- 子表的表结构不能直接修改,但可以修改超级表的列和标签,且修改对所有子表立即生效。
- 超级表定义了一个模板,自身并不存储任何数据或标签信息。
在 TDengine 中查询操作既可以在子表上进行也可以在超级表上进行。针对超级表的查询TDengine 将所有子表中的数据视为一个整体首先通过标签筛选出满足查询条件的表然后在这些子表上分别查询时序数据最终将各张子表的查询结果合并。本质上TDengine 通过对超级表查询的支持,实现了多个同类数据采集点的高效聚合。为了更好地理解采集量、标签、超级表与子表之间的关系,这里以智能电表的数据模型为例进行说明。可以参考图 3-1 的数据模型,以便更直观地了解这些概念。
为了更好地理解采集量、标签、超级与子表的关系,以智能电表为例,可以参考下图
![数据模型示意图](./data-model.png)
### 库
库是 TDengine 中用于管理一组表的集合。TDengine 允许一个运行实例包含多个库,并且每个库都可以配置不同的存储策略。由于不同类型的数据采集点通常具有不同的数据特征,如数据采集频率、数据保留期限、副本数量、数据块大小等。为了在各种场景下确保 TDengine 能够发挥最大效率,建议将具有不同数据特征的超级表创建在不同的库中。
在一个库中,可以包含一到多张超级表,但每张超级表只能属于一个库。同时,一张超级表所拥有的所有子表也都将存储在该库中。这种设计有助于实现更细粒度的数据管理和优化,确保 TDengine 能够根据不同数据特征提供最佳的处理性能。
### 时间戳
时间戳在时序数据处理中扮演着至关重要的角色,特别是在应用程序需要从多个不同时区访问数据库时,这一问题变得更加复杂。在深入了解 TDengine 如何处理时间戳与时区之前,我们先介绍以下几个基本概念。
- 本地日期时间:指特定地区的当地时间,通常表示为 yyyy-MM-dd hh:mm:ss.SSS 格 式 的 字 符 串。 这 种 时 间 表 示 不 包 含 任 何 时 区 信 息, 如“2021-07-21 12:00:00.000”。
- 时区地球上不同地理位置的标准时间。协调世界时Universal Time CoordinatedUTC或格林尼治时间是国际时间标准其他时区通常表示为相对于 UTC 的偏移量如“UTC+8”代表东八区时间。 UTC 时间戳:表示自 UNIX 纪 元(即 UTC 时 间 1970 年 1 月 1 日 0 点) 起 经 过的毫秒数。例如“1700000000000”对应的日期时间是“2023-11-14 22:13:20UTC+0”。 在 TDengine 中保存时序数据时,实际上保存的是 UTC 时间戳。TDengine 在写入数据时,时间戳的处理分为如下两种情况。
- RFC-3339 格式当使用这种格式时TDengine 能够正确解析带有时区信息的时间字符串为 UTC 时间戳。例如“2018-10-03T14:38:05.000+08:00”会被转换为UTC 时间戳。
- 非 RFC-3339 格式如果时间字符串不包含时区信息TDengine 将使用应用程序所在的时区设置自动将时间转换为 UTC 时间戳。
在查询数据时TDengine 客户端会根据应用程序当前的时区设置自动将保存的UTC 时间戳转换成本地时间进行显示,确保用户在不同时区下都能看到正确的时间信息。
## 数据建模
本节用智能电表做例子,简要的介绍如何在 TDengine 里使用 SQL 创建数据库、超级表、表的基本操作。
### 创建数据库
创建一个数据库以存储电表数据的 SQL 如下:
```sql
CREATE DATABASE power PRECISION 'ms' KEEP 3650 DURATION 10 BUFFER 16;
```
该 SQL 将创建一个名为 `power` 的数据库,各参数说明如下:
- `PRECISION 'ms'` 这个数据库的时序数据使用毫秒ms精度的时间戳
- `KEEP 365`:这个库的数据将保留 3650 天,超过 3650 天的数据将被自动删除
- `DURATION 10` :每 10 天的数据放在一个数据文件中
- `BUFFER 16` :写入使用大小为 16MB 的内存池。
在创建power数据库后可以执行 USE 语句来使用切换数据库。
```sql
use power;
```
该 SQL 将当前数据库切换为 `power`,表示之后的插入、查询等操作,都在当前的 `power` 数据库中进行。
### 创建超级表
创建一张名为 `meters` 的超级表的 SQL 如下:
```sql
CREATE STABLE meters (
ts timestamp,
current float,
voltage int,
phase float
) TAGS (
location varchar(64),
group_id int
);
```
在 TDengine 中,创建超级表的 SQL 语句与关系型数据库类似。例如,上面的 SQL 中,`CREATE STABLE` 为关键字,表示创建超级表;接着,`meters` 是超级表的名称;在表名后面的括号中,定义超级表的列(列名、数据类型等),规则如下:
1. 第 1 列必须为时间戳列。例如:`ts timestamp` 表示,时间戳列名是 `t`s数据类型为 `timestamp`
2. 从第 2 列开始是采集量列。采集量的数据类型可以为整型、浮点型、字符串等。例如:`current float` 表示,采集量电流 `current`,数据类型为 `float`
最后TAGS是关键字表示标签在 TAGS 后面的括号中,定义超级表的标签(标签名、数据类型等)。
1. 标签的数据类型可以为整型、浮点型、字符串等。例如:`location varchar(64)` 表示,标签地区 `location`,数据类型为 `varchar(64)`
2. 标签的名称不能与采集量列的名称相同。
### 创建表
通过超级表创建子表 `d1001` 的 SQL 如下:
```sql
CREATE TABLE d1001
USING meters (
location,
group_id
) TAGS (
"California.SanFrancisco",
2
);
```
上面的 SQL 中,`CREATE TABLE` 为关键字,表示创建表;`d1001` 是子表的名称;`USING` 是关键字,表示要使用超级表作为模版;`meters` 是超级表的名称;在超级表名后的括号中,`location`, `group_id` 表示,是超级表的标签列名列表;`TAGS` 是关键字,在后面的括号中指定子表的标签列的值。`"California.SanFrancisco"` 和 `2` 表示子表 `d1001` 的位置为 `California.SanFrancisco`,分组 ID 为 `2`
当对超级表进行写入或查询操作时,用户可以使用伪列 tbname 来指定或输出对应操作的子表名。
### 自动建表
在 TDengine 中,为了简化用户操作并确保数据的顺利写入,即使子表尚不存在,用户也可以使用带有 using 关键字的自动建表 SQL 进行数据写入。这种机制允许系统在遇到不存在的子表时,自动创建该子表,然后再执行数据写入操作。如果子表已经存在,系统则会直接写入数据,不需要任何额外的步骤。
在写入数据的同时自动建表的 SQL 如下:
```sql
INSERT INTO d1002
USING meters
TAGS (
"California.SanFrancisco",
2
) VALUES (
NOW,
10.2,
219,
0.32
);
```
上面的 SQL 中,`INSERT INTO d1002` 表示,向子表 `d1002` 中写入数据;`USING meters` 表示,使用超级表 `meters` 作为模版;`TAGS ("California.SanFrancisco", 2)` 表示,子表 `d1002` 的标签值分别为 `California.SanFrancisco``2``VALUES (NOW, 10.2, 219, 0.32)` 表示,向子表 `d1002` 插入一行记录值分别为NOW当前时间戳、10.2电流、219电压、0.32(相位)。在 TDengine 执行这条 SQL 时,如果子表 `d1002` 已经存在,则直接写入数据;当子表 `d1002` 不存在,会先自动创建子表,再写入数据。
### 创建普通表
在 TDengine 中,除了具有标签的子表以外,还存在一种不带任何标签的普通表。这类表与普通关系型数据库中的表相似,用户可以使用 SQL 创建它们。
普通表与子表的区别在于:
1. 标签扩展性:子表在普通表的基础上增加了静态标签,这使得子表能够携带更多的元数据信息。此外,子表的标签是可变的,用户可以根据需要增加、删除或修改标签。
2. 表归属:子表总是隶属于某张超级表,它们是超级表的一部分。而普通表则独立存在,不属于任何超级表。
3. 转换限制:在 TDengine 中,普通表无法直接转换为子表,同样,子表也无法转换为普通表。这两种表类型在创建时就确定了它们的结构和属性,后期无法更改。
总结来说,普通表提供了类似于传统关系型数据库的表功能,而子表则通过引入标签机制,为时序数据提供了更丰富的描述能力和更灵活的管理方式。用户可以根据实际需求选择创建普通表还是子表。
创建不带任何标签的普通表的 SQL 如下:
```sql
CREATE TABLE d1003(
ts timestamp,
current float,
voltage int,
phase float,
location varchar(64),
group_id int
);
```
上面的 SQL 表示,创建普通表 `d1003` ,表结构包括 `ts`、`current`、`voltage`、`phase`、`location`、`group_id`,共 6 个列。这样的数据模型,与关系型数据库完全一致。
采用普通表作为数据模型意味着静态标签数据(如 location 和 group_id会重复存储在表的每一行中。这种做法不仅增加了存储空间的消耗而且在进行查询时由于无法直接利用标签数据进行过滤查询性能会显著低于使用超级表的数据模型。
### 多列模型 VS 单列模型
TDengine 支持灵活的数据模型设计,包括多列模型和单列模型。多列模型允许将多个由同一数据采集点同时采集且时间戳一致的物理量作为不同列存储在同一张超级表中。然而,在某些极端情况下,可能会采用单列模型,即每个采集的物理量都单独建立一张表。例如,对于电流、电压和相位这 3 种物理量,可能会分别建立 3 张超级表。
尽管 TDengine 推荐使用多列模型,因为这种模型在写入效率和存储效率方面通常更优,但在某些特定场景下,单列模型可能更为适用。例如,当一个数据采集点的采集量种类经常发生变化时,如果采用多列模型,就需要频繁修改超级表的结构定义,这会增加应用程序的复杂性。在这种情况下,采用单列模型可以简化应用程序的设计和管理,因为它允许独立地管理和扩展每个物理量的超级表。
总之TDengine 提供了灵活的数据模型选项,用户可以根据实际需求和场景选择最适合的模型,以优化性能和管理复杂性。

View File

@ -0,0 +1,135 @@
---
sidebar_label: 数据写入
title: TDengine 数据写入、更新与删除
toc_max_heading_level: 4
---
本章以智能电表的数据模型为例介绍如何在 TDengine 中使用 SQL 来写入、更新、删除时序数据。
## 写入
在 TDengine 中,用户可以使用 SQL 的 insert 语句写入时序数据。
### 一次写入一条
假设设备 ID 为 d1001 的智能电表在 2018 年 10 月 3 日 14:38:05 采集到数据电流10.3A,电压 219V相位 0.31。在第 3 章中,我们已经在 TDengine 的 power 数据库中创建了属于超级表 meters 的子表 d1001。接下来可以通过下面的 insert 语句在子表 d1001 中写入时序数据。
1. 可以通过下面的 INSERT 语句向子表d1001中写入时序数据。
```sql
insert into d1001 (ts, current, voltage, phase) values ( "2018-10-03 14:38:05", 10.3, 219, 0.31)
```
上面的 SQL 向子表 `d1001``ts`, `current`, `voltage`, `phase` 这 4 列分别写入 `2018-10-03 14:38:05`, `10.3`, `219`, `0.31`
2. 当 `INSERT` 语句中的 `VALUES` 部分包含了表的所有列时,可以省略 `VALUES` 前的字段列表,如下面的 SQL 语句所示,其与前面指定列的 INSERT 语句,效果完全一样。
```sql
insert into d1001 values("2018-10-03 14:38:05", 10.3, 219, 0.31)
```
3. 对于表的时间戳列(第一列),也可以直接使用数据库精度的时间戳。
```sql
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31);
```
以上三种 SQL 的效果完全相同。
### 一次写入多条
假设设备 ID 为 d1001 的智能电表每 10s 采集一次数据,每 30s 上报一次数据,即每 30s 需要写入 3 条数据。用户可以在一条 insert 语句中写入多条记录。如下 SQL 一共写入了 3 条数据。
```sql
insert into d1001 values
( "2018-10-03 14:38:05", 10.2, 220, 0.23),
( "2018-10-03 14:38:15", 12.6, 218, 0.33),
( "2018-10-03 14:38:25", 12.3, 221, 0.31)
```
上面的 SQL 一共写入了三条数据。
### 一次写入多表
假设设备 ID 为 d1001、d1002、d1003 的 3 台智能电表,都是每 30 秒需要写入 3 条数据。对于这种情况TDengine 支持一次向多个表写入多条数据。
```sql
INSERT INTO d1001 VALUES
("2018-10-03 14:38:05", 10.2, 220, 0.23),
("2018-10-03 14:38:15", 12.6, 218, 0.33),
("2018-10-03 14:38:25", 12.3, 221, 0.31)
d1002 VALUES
("2018-10-03 14:38:04", 10.2, 220, 0.23),
("2018-10-03 14:38:14", 10.3, 218, 0.25),
("2018-10-03 14:38:24", 10.1, 220, 0.22)
d1003 VALUES
("2018-10-03 14:38:06", 11.5, 221, 0.35),
("2018-10-03 14:38:16", 10.4, 220, 0.36),
("2018-10-03 14:38:26", 10.3, 220, 0.33)
;
```
上面的 SQL 一共写入了九条数据。
### 指定列写入
可以通过指定列向表的部分列写入数据。SQL 中没有出现的列数据库将自动填充为空值NULL。注意时间戳列必须存在且值不能为空。如下 SQL 向子表 d1004 写入了一条数据。这条数据只包含电压和相位,电流值为 NULL。
```sql
insert into d1004 (ts, voltage, phase) values("2018-10-04 14:38:06", 223, 0.29)
```
### 写入时自动建表
用户可以使用带有 using 关键字的自动建表语句进行写入。当子表不存在时,先触发自动建表,再写入数据;当子表已经存在时,则直接写入。使用自动建表的 insert 语句也可以通过指定部分标签列进行写入未被指定的标签列的值为空值NULL。如下 SQL 写入一条数据。当子表 d1005 不存在时,先自动建表,标签 group_id 的值为 NULL再写入数据
```sql
insert into d1005
using meters (location)
tags ( "beijing.chaoyang")
values ( "2018-10-04 14:38:07", 10.15, 217, 0.33)
```
自动建表的 insert 语句也支持在一条语句中向多张表写入数据。如下 SQL 使用自动建表的 insert 语句共写入 9 条数据。
```sql
INSERT INTO d1001 USING meters TAGS ("California.SanFrancisco", 2) VALUES
("2018-10-03 14:38:05", 10.2, 220, 0.23),
("2018-10-03 14:38:15", 12.6, 218, 0.33),
("2018-10-03 14:38:25", 12.3, 221, 0.31)
d1002 USING meters TAGS ("California.SanFrancisco", 3) VALUES
("2018-10-03 14:38:04", 10.2, 220, 0.23),
("2018-10-03 14:38:14", 10.3, 218, 0.25),
("2018-10-03 14:38:24", 10.1, 220, 0.22)
d1003 USING meters TAGS ("California.LosAngeles", 2) VALUES
("2018-10-03 14:38:06", 11.5, 221, 0.35),
("2018-10-03 14:38:16", 10.4, 220, 0.36),
("2018-10-03 14:38:26", 10.3, 220, 0.33)
;
```
### 通过超级表写入
TDengine 还支持直接向超级表写入数据。需要注意的是,超级表是一个模板,本身不存储数据,写入的数据是存储在对应的子表中。如下 SQL 通过指定 tbname 列向子表d1001 写入一条数据。
```sql
insert into meters (tbname, ts, current, voltage, phase, location, group_id)
values( "d1001v, "2018-10-03 14:38:05", 10.2, 220, 0.23, "California.SanFrancisco", 2)
```
### 零代码写入
为了方便用户轻松写入数据TDengine 已与众多知名第三方工具实现无缝集成,包括 Telegraf、Prometheus、EMQX、StatsD、collectd 和 HiveMQ 等。用户只须对这些工具进行简单的配置,便可轻松将数据导入 TDengine。此外TDengine Enterprise 还提供了丰富的连接器,如 MQTT、OPC、AVEVA PI System、Wonderware、Kafka、MySQL、Oracle 等。通过在 TDengine 端配置相应的连接信息,用户无须编写任何代码,即可高效地将来自不同数据源的数据写入 TDengine。
## 更新
可以通过写入重复时间戳的一条数据来更新时序数据,新写入的数据会替换旧值。 下面的 SQL通过指定列的方式向子表 `d1001` 中写入 1 行数据;当子表 `d1001` 中已经存在日期时间为 `2018-10-03 14:38:05` 的数据时,`current`电流的新值22会替换旧值。
```sql
INSERT INTO d1001 (ts, current) VALUES ("2018-10-03 14:38:05", 22);
```
## 删除
为方便用户清理由于设备故障等原因产生的异常数据TDengine 支持根据时间戳删除时序数据。 下面的 SQL将超级表 `meters` 中所有时间戳早于 `2021-10-01 10:40:00.100` 的数据删除。数据删除后不可恢复,请慎重使用。为了确保删除的数据确实是自己要删除的,建议可以先使用 select 语句加 where 后的删除条件查看要删除的数据内容,确认无误后再执行 delete 。
```sql
delete from meters where ts < '2021-10-01 10:40:00.100' ;
```

View File

@ -0,0 +1,666 @@
---
sidebar_label: 数据查询
title: TDengine 数据查询
toc_max_heading_level: 4
---
相较于其他众多时序数据库和实时数据库TDengine 的一个独特优势在于,自其首个版本发布之初便支持标准的 SQL 查询功能。这一特性极大地降低了用户在使用过程中的学习难度。本章将以智能电表的数据模型为例介绍如何在 TDengine 中运用 SQL 查询来处理时序数据。如果需要进一步了解 SQL 语法的细节和功能,建议参阅 TDengine 的官方文档。通过本章的学习,你将能够熟练掌握 TDengine 的 SQL 查询技巧,进而高效地对时序数据进行操作和分析。
## 基本查询
为了更好的介绍 TDengine 数据查询,使用 如下 taosBenchmark 命令,生成本章内容需要的时序数据。
```shell
taosBenchmark --start-timestamp=1600000000000 --tables=100 --records=10000000 --time-step=10000
```
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的数据库,产生共 10 亿条时序数据。时序数据的时间戳从 `1600000000000`2020-09-13T20:26:40+08:00开始包含 `100` 个设备(子表),每个设备有 `10000000` 条数据,时序数据的采集频率是 10 秒/ 条。
在 TDengine 中,用户可以通过 WHERE 语句指定条件,查询时序数据。以智能电表的数据为例
```sql
SELECT * FROM meters
WHERE voltage > 10
ORDER BY ts DESC
LIMIT 5
```
上面的 SQL从超级表 `meters` 中查询出电压 `voltage` 大于 10 的记录,按时间降序排列,且仅输出前 5 行。查询结果如下:
```text
ts | current | voltage | phase | groupid | location |
==========================================================================================================
2023-11-14 22:13:10.000 | 1.1294620 | 18 | 0.3531540 | 8 | California.MountainView |
2023-11-14 22:13:10.000 | 1.0294620 | 12 | 0.3631540 | 2 | California.Campbell |
2023-11-14 22:13:10.000 | 1.0294620 | 16 | 0.3531540 | 1 | California.Campbell |
2023-11-14 22:13:10.000 | 1.1294620 | 18 | 0.3531540 | 2 | California.Campbell |
2023-11-14 22:13:10.000 | 1.1294620 | 16 | 0.3431540 | 7 | California.PaloAlto |
```
## 聚合查询
TDengine 支持通过 GROUP BY 子句对数据进行聚合查询。SQL 语句包含 GROUP BY 子句时SELECT 列表只能包含如下表达式:
1. 常量
2. 聚集函数
3. 与 GROUP BY 后表达式相同的表达式
4. 包含前面表达式的表达式
group by 子句用于对数据进行分组,并为每个分组返回一行汇总信息。在 group by 子句中,可以使用表或视图中的任何列作为分组依据,这些列不需要出现在 select 列表中。此外,用户可以直接在超级表上执行聚合查询,无须预先创建子表。以智能电表的数据模型为例,使用 group by 子句的 SQL 如下:
```sql
SELECT groupid,avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2023-01-01T00:00:00+08:00"
GROUP BY groupid
```
上面的 SQL查询超级表 `meters` 中,时间戳大于等于 `2022-01-01T00:00:00+08:00`,且时间戳小于 `2023-01-01T00:00:00+08:00` 的数据,按照 `groupid` 进行分组,求每组的平均电压。查询结果如下:
```text
groupid | avg(voltage) |
==========================================
8 | 9.104040404040404 |
5 | 9.078333333333333 |
1 | 9.087037037037037 |
7 | 8.991414141414142 |
9 | 8.789814814814815 |
6 | 9.051010101010101 |
4 | 9.135353535353536 |
10 | 9.213131313131314 |
2 | 9.008888888888889 |
3 | 8.783888888888889 |
Query OK, 10 row(s) in set (0.042446s)
```
**注意**: group by 子句在聚合数据时,并不保证结果集按照特定顺序排列。为了获得有序的结果集,可以使用 order by 子句对结果进行排序。这样,可以根据需要调整输出结果的顺序,以满足特定的业务需求或报告要求。
TDengine 提供了多种内置的聚合函数。如下表所示:
| 聚合函数 | 功能说明 |
|:----------------------:|:--------------------------------------------------------------:|
|APERCENTILE | 统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。 |
|AVG | 统计指定字段的平均值 |
|COUNT | 统计指定字段的记录行数 |
|ELAPSED|elapsed 函数表达了统计周期内连续的时间长度,和 twa 函数配合使用可以计算统计曲线下的面积。在通过 INTERVAL 子句指定窗口的情况下,统计在给定时间范围内的每个窗口内有数据覆盖的时间范围;如果没有 INTERVAL 子句则返回整个给定时间范围内的有数据覆盖的时间范围。注意ELAPSED 返回的并不是时间范围的绝对值,而是绝对值除以 time_unit 所得到的单位个数。|
|LEASTSQUARES | 统计表中某列的值的拟合直线方程。start_val 是自变量初始值step_val 是自变量的步长值。 |
|SPREAD | 统计表中某列的最大值和最小值之差。|
|STDDEV | 统计表中某列的均方差。 |
|SUM | 统计表/超级表中某列的和。 |
|HYPERLOGLOG | 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。在数据量较少的时候该算法不是很准确,可以使用 select countdata from select uniquecol as data from table 的方法。 |
|HISTOGRAM | 统计数据按照用户指定区间的分布。 |
|PERCENTILE | 统计表中某列的值百分比分位数。|
## 数据切分查询
TDengine 支持 PARTITION BY 子句。当需要按一定的维度对数据进行切分,然后在切分出的数据空间内再进行一系列的计算时,可以使用 PARTITION BY 子句进行查询,语法如下:
```sql
PARTITION BY part_list
```
`part_list` 可以是任意的标量表达式,包括列、常量、标量函数和它们的组合。
TDengine 按如下方式处理数据切分子句。
1. 数据切分子句位于 WHERE 子句之后;
2. 数据切分子句将表数据按指定的维度进行切分每个切分的分片进行指定的计算。计算由之后的子句定义窗口子句、GROUP BY 子句或 SELECT 子句);
3. 数据切分子句可以和窗口切分子句(或 GROUP BY 子句)一起使用,此时后面的子句作用在每个切分的分片上。
数据切分的 SQL 如下s
```sql
SELECT location, avg(voltage)
FROM meters
PARTITION BY location
```
上面的示例 SQL 查询超级表 `meters`,将数据按标签 `location` 进行分组,每个分组计算电压的平均值。查询结果如下:
```text
location | avg(voltage) |
=========================================================
California.SantaClara | 8.793334320000000 |
California.SanFrancisco | 9.017645882352941 |
California.SanJose | 9.156112940000000 |
California.LosAngles | 9.036753507692307 |
California.SanDiego | 8.967037053333334 |
California.Sunnyvale | 8.978572085714285 |
California.PaloAlto | 8.936665800000000 |
California.Cupertino | 8.987654066666666 |
California.MountainView | 9.046297266666667 |
California.Campbell | 9.149999028571429 |
Query OK, 10 row(s) in set (2.415961s)
```
## 窗口切分查询
在 TDengine 中,你可以使用窗口子句来实现按时间窗口切分方式进行聚合结果查询,这种查询方式特别适用于需要对大量时间序列数据进行分析的场景,例如智能电表每 10s 采集一次数据,但需要查询每隔 1min 的温度平均值。
窗口子句允许你针对查询的数据集合按照窗口进行切分,并对每个窗口内的数据进行聚合,包含:
- 时间窗口time window
- 状态窗口status window
- 会话窗口session window
- 事件窗口event window
窗口划分逻辑如下图所示:
![常用窗口划分逻辑](./window.png)
窗口子句语法如下:
```sql
window_clause: {
SESSION(ts_col, tol_val)
| STATE_WINDOW(col)
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
| EVENT_WINDOW START WITH start_trigger_condition END WITH end_trigger_condition
}
```
**注意** 在使用窗口子句时应注意以下规则:
1. 窗口子句位于数据切分子句之后,不可以和 GROUP BY 子句一起使用。
2. 窗口子句将数据按窗口进行切分,对每个窗口进行 SELECT 列表中的表达式的计算SELECT 列表中的表达式只能包含常量伪列_wstart 伪列、_wend 伪列和 _wduration 伪列;聚集函数(包括选择函数和可以由参数确定输出行数的时序特有函数)
3. WHERE 语句可以指定查询的起止时间和其他过滤条件。
### 时间戳伪列
在窗口聚合查询结果中,如果 SQL 中没有指定输出查询结果中的时间戳列,那么最终结果中将不会自动包含窗口的时间列信息。然而,如果你需要在结果中输出聚合查询结果所对应的时间窗口信息,可以在 select 子句中使用与时间戳相关的伪列如时间窗口起始时间_wstart、时间窗口结束时间_wend、时间窗口持续时间_wduration以及与查询整体窗口相关的伪列如查询窗口起始时间_qstart和查询窗口结束时间_qend。需要注意的是时间窗口起始时间和结束时间均是闭区间时间窗口持续时间是数据当前时间分辨率下的数值。例如如果当前数据库的时间精度是毫秒ms那么结果中的 500 表示当前时间窗口的持续时间是 500ms。
### 时间窗口
时间窗口可分为:滑动时间窗口、翻转时间窗口。时间窗口子句的语法如下:
```sql
INTERVAL(interval_val [, interval_offset])
[SLIDING (sliding_val)]
[FILL(fill_mod_and_val)]
```
时间窗口子句包括 3 个子句:
- INTERVAL 子句用于产生相等时间周期的窗口interval_val 指定每个时间窗口的大小interval_offset 指定;
- SLIDING 子句:用于指定窗口向前滑动的时间;
- FILL用于指定窗口区间数据缺失的情况下数据的填充模式。
对于时间窗口interval_val 和 sliding_val 都表示时间段, 语法上支持三种方式。例如:
1. INTERVAL(1s, 500a) SLIDING(1s),带时间单位的形式,其中的时间单位是单字符表示, 分别为: a (毫秒), b (纳秒), d (天), h (小时), m (分钟), n (月), s (秒), u (微妙), w (周), y (年);
2. INTERVAL(1000, 500) SLIDING(1000),不带时间单位的形式,将使用查询库的时间精度作为默认时间单位,当存在多个库时默认采用精度更高的库;
3. INTERVAL('1s', '500a') SLIDING('1s'),带时间单位的字符串形式,字符串内部不能有任何空格等其它字符。
示例 SQL 如下:
```sql
SELECT tbname, _wstart, _wend, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
INTERVAL(1m, 5s)
SLIMIT 2;
```
上面的 SQL查询超级表 `meters` 中,时间戳大于等于 `2022-01-01T00:00:00+08:00`,且时间戳小于 `2022-01-01T00:05:00+08:00` 的数据;数据首先按照子表名 `tbname` 进行数据切分,再按照每 1 分钟的时间窗口进行切分,且每个时间窗口向后偏移 5 秒;最后,仅取前 2 个分片的数据作为结果。查询结果如下:
```text
tbname | _wstart | _wend | avg(voltage) |
==========================================================================================
d40 | 2021-12-31 15:59:05.000 | 2021-12-31 16:00:05.000 | 4.000000000000000 |
d40 | 2021-12-31 16:00:05.000 | 2021-12-31 16:01:05.000 | 5.000000000000000 |
d40 | 2021-12-31 16:01:05.000 | 2021-12-31 16:02:05.000 | 8.000000000000000 |
d40 | 2021-12-31 16:02:05.000 | 2021-12-31 16:03:05.000 | 7.666666666666667 |
d40 | 2021-12-31 16:03:05.000 | 2021-12-31 16:04:05.000 | 9.666666666666666 |
d40 | 2021-12-31 16:04:05.000 | 2021-12-31 16:05:05.000 | 15.199999999999999 |
d41 | 2021-12-31 15:59:05.000 | 2021-12-31 16:00:05.000 | 4.000000000000000 |
d41 | 2021-12-31 16:00:05.000 | 2021-12-31 16:01:05.000 | 7.000000000000000 |
d41 | 2021-12-31 16:01:05.000 | 2021-12-31 16:02:05.000 | 9.000000000000000 |
d41 | 2021-12-31 16:02:05.000 | 2021-12-31 16:03:05.000 | 10.666666666666666 |
d41 | 2021-12-31 16:03:05.000 | 2021-12-31 16:04:05.000 | 8.333333333333334 |
d41 | 2021-12-31 16:04:05.000 | 2021-12-31 16:05:05.000 | 9.600000000000000 |
Query OK, 12 row(s) in set (0.021265s)
```
#### 滑动窗口
每次执行的查询是一个时间窗口时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口time window 大小和每次前向增量时间forward sliding times。如下图[t0s t0e] [t1s t1e] [t2s t2e] 是分别是执行三次连续查询的时间窗口范围,窗口的前向滑动的时间范围 sliding time 标识 。查询过滤、聚合等操作按照每个时间窗口为独立的单位执行。
![时间窗口示意图](./sliding-window.png)
**注意**
1. INTERVAL 和 SLIDING 子句需要配合聚合和选择函数来使用,因此,下面的 SQL 语句是非法的:
```sql
SELECT COUNT(*) FROM temp_tb_1 INTERVAL(1m) SLIDING(2m);
```
2. SLIDING 的向前滑动的时间不能超过一个窗口的时间范围,因此,下面的 SQL 语句也是非法的:
```sql
SELECT COUNT(*) FROM temp_tb_1 INTERVAL(1m) SLIDING(2m);
```
**使用时间窗口需要注意**
1. 聚合时间段的窗口宽度由关键词 INTERVAL 指定,最短时间间隔 10 毫秒10a并且支持偏移 offset偏移必须小于间隔也即时间窗口划分与“UTC 时刻 0”相比的偏移量。SLIDING 语句用于指定聚合时间段的前向增量,也即每次窗口向前滑动的时长。
2. 使用 INTERVAL 语句时,除非极特殊的情况,都要求把客户端和服务端的 taos.cfg 配置文件中的 timezone 参数配置为相同的取值,以避免时间处理函数频繁进行跨时区转换而导致的严重性能影响。
3. 返回的结果中时间序列严格单调递增。
示例:
```sql
SELECT tbname, _wstart, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
INTERVAL(1m) SLIDING(30s)
SLIMIT 1;
```
上面的 SQL查询超级表 `meters` 中,时间戳大于等于 `2022-01-01T00:00:00+08:00`,且时间戳小于 `2022-01-01T00:05:00+08:00` 的数据,数据首先按照子表名 `tbname` 进行数据切分,再按照每 1 分钟的时间窗口进行切分,且时间窗口按照 30 秒进行滑动;最后,仅取前 1 个分片的数据作为结果。查询结果如下:
```text
tbname | _wstart | avg(voltage) |
================================================================
d40 | 2021-12-31 15:59:30.000 | 4.000000000000000 |
d40 | 2021-12-31 16:00:00.000 | 5.666666666666667 |
d40 | 2021-12-31 16:00:30.000 | 4.333333333333333 |
d40 | 2021-12-31 16:01:00.000 | 5.000000000000000 |
d40 | 2021-12-31 16:01:30.000 | 9.333333333333334 |
d40 | 2021-12-31 16:02:00.000 | 9.666666666666666 |
d40 | 2021-12-31 16:02:30.000 | 10.000000000000000 |
d40 | 2021-12-31 16:03:00.000 | 10.333333333333334 |
d40 | 2021-12-31 16:03:30.000 | 10.333333333333334 |
d40 | 2021-12-31 16:04:00.000 | 13.000000000000000 |
d40 | 2021-12-31 16:04:30.000 | 15.333333333333334 |
Query OK, 11 row(s) in set (0.013153s)
```
#### 翻转窗口
当 SLIDING 与 INTERVAL 相等的时候,滑动窗口即为翻转窗口。翻转窗口和滑动窗口的区别在于,滑动窗口因为 interval_val 和 sliding_val 不同,不同时间窗口之间,会存在数据重叠,翻转窗口则没有数据重叠。本质上,翻转窗口就是按照 interval_val 进行了时间窗口划分INTERVAL(1m)和INTERVAL(1m) SLIDING(1m)是等效的。
示例:
```sql
SELECT tbname, _wstart, _wend, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
INTERVAL(1m) SLIDING(1m)
SLIMIT 1;
```
上面的 SQL查询超级表 `meters` 中,时间戳大于等于 `2022-01-01T00:00:00+08:00`,且时间戳小于 `2022-01-01T00:05:00+08:00` 的数据,数据首先按照子表名 `tbname` 进行数据切分,再按照每 1 分钟的时间窗口进行切分,且时间窗口按照 1 分钟进行切分;最后,仅取前 1 个分片的数据作为结果。查询结果如下:
```text
tbname | _wstart | _wend | avg(voltage) |
=================================================================================================================
d28 | 2021-12-31 16:00:00.000 | 2021-12-31 16:01:00.000 | 7.333333333333333 |
d28 | 2021-12-31 16:01:00.000 | 2021-12-31 16:02:00.000 | 8.000000000000000 |
d28 | 2021-12-31 16:02:00.000 | 2021-12-31 16:03:00.000 | 11.000000000000000 |
d28 | 2021-12-31 16:03:00.000 | 2021-12-31 16:04:00.000 | 6.666666666666667 |
d28 | 2021-12-31 16:04:00.000 | 2021-12-31 16:05:00.000 | 10.000000000000000 |
Query OK, 5 row(s) in set (0.016812s)
```
#### FILL 子句
FILL 子句,用于指定某一窗口区间数据缺失的情况下的填充模式。填充模式包括以下几种:
1. 不进行填充NONE默认填充模式
2. VALUE 填充固定值填充此时需要指定填充的数值。例如FILLVALUE 1.23)。这里需要注意,最终填充的值受由相应列的类型决定,如 FILLVALUE 1.23),相应列为 INT 类型,则填充值为 1。
3. PREV 填充:使用前一个非 NULL 值填充数据。例如FILLPREV
4. NULL 填充:使用 NULL 填充数据。例如FILLNULL
5. LINEAR 填充:根据前后距离最近的非 NULL 值做线性插值填充。例如FILLLINEAR
6. NEXT 填充:使用下一个非 NULL 值填充数据。例如FILLNEXT
以上填充模式中,除了 NONE 模式默认不填充值之外,其他模式在查询的整个时间范围内如果没有数据 FILL 子句将被忽略即不产生填充数据查询结果为空。这种行为在部分模式PREV、NEXT、LINEAR下具有合理性因为在这些模式下没有数据意味着无法产生填充数值。
对另外一些模式NULL、VALUE来说理论上是可以产生填充数值的至于需不需要输出填充数值取决于应用的需求。所以为了满足这类需要强制填充数据或 NULL 的应用的需求同时不破坏现有填充模式的行为兼容性TDengine 还支持两种新的填充模式:
1. NULL_F: 强制填充 NULL 值
2. VALUE_F: 强制填充 VALUE 值
NULL、 NULL_F、 VALUE、 VALUE_F 这几种填充模式针对不同场景区别如下:
1. INTERVAL 子句: NULL_F VALUE_F 为强制填充模式NULL VALUE 为非强制模式。在这种模式下下各自的语义与名称相符
2. 流计算中的 INTERVAL 子句NULL_F 与 NULL 行为相同均为非强制模式VALUE_F 与 VALUE 行为相同,均为非强制模式。即流计算中的 INTERVAL 没有强制模式
3. INTERP 子句NULL 与 NULL_F 行为相同均为强制模式VALUE 与 VALUE_F 行为相同,均为强制模式。即 INTERP 中没有非强制模式。
**注意**
1. 使用 FILL 语句的时候可能生成大量的填充输出,务必指定查询的时间区间。
2. 针对每次查询,系统可返回不超过 1 千万条具有插值的结果。
3. 在时间维度聚合中,返回的结果中时间序列严格单调递增。
4. 如果查询对象是超级表,则聚合函数会作用于该超级表下满足值过滤条件的所有表的数据。如果查询中没有使用 PARTITION BY 语句,则返回的结果按照时间序列严格单调递增;如果查询中使用了 PARTITION BY 语句分组,则返回结果中每个 PARTITION 内按照时间序列严格单调递增。
示例:
```sql
SELECT tbname, _wstart, _wend, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
INTERVAL(1m) FILL(prev)
SLIMIT 2;
```
上面的 SQL查询超级表 `meters` 中,时间戳大于等于 `2022-01-01T00:00:00+08:00`,且时间戳小于 `2022-01-01T00:05:00+08:00` 的数据;数据首先按照子表名 `tbname` 进行数据切分,再按照每 1 分钟的时间窗口进行切分,如果窗口内的数据出现缺失,则使用使用前一个非 NULL 值填充数据;最后,仅取前 2 个分片的数据作为结果。查询结果如下:
```text
tbname | _wstart | _wend | avg(voltage) |
=================================================================================================================
d40 | 2021-12-31 16:00:00.000 | 2021-12-31 16:01:00.000 | 5.666666666666667 |
d40 | 2021-12-31 16:01:00.000 | 2021-12-31 16:02:00.000 | 5.000000000000000 |
d40 | 2021-12-31 16:02:00.000 | 2021-12-31 16:03:00.000 | 9.666666666666666 |
d40 | 2021-12-31 16:03:00.000 | 2021-12-31 16:04:00.000 | 10.333333333333334 |
d40 | 2021-12-31 16:04:00.000 | 2021-12-31 16:05:00.000 | 13.000000000000000 |
d41 | 2021-12-31 16:00:00.000 | 2021-12-31 16:01:00.000 | 5.666666666666667 |
d41 | 2021-12-31 16:01:00.000 | 2021-12-31 16:02:00.000 | 9.333333333333334 |
d41 | 2021-12-31 16:02:00.000 | 2021-12-31 16:03:00.000 | 11.000000000000000 |
d41 | 2021-12-31 16:03:00.000 | 2021-12-31 16:04:00.000 | 7.666666666666667 |
d41 | 2021-12-31 16:04:00.000 | 2021-12-31 16:05:00.000 | 10.000000000000000 |
Query OK, 10 row(s) in set (0.022866s)
```
### 状态窗口
使用整数布尔值或字符串来标识产生记录时候设备的状态量。产生的记录如果具有相同的状态量数值则归属于同一个状态窗口数值改变后该窗口关闭。TDengine 还支持将 CASE 表达式用在状态量,可以表达某个状态的开始是由满足某个条件而触发,这个状态的结束是由另外一个条件满足而触发的语义。以智能电表为例,电压正常范围是 205V 到 235V那么可以通过监控电压来判断电路是否正常。
```sql
SELECT tbname, _wstart, _wend,_wduration, CASE WHEN voltage >= 205 and voltage <= 235 THEN 1 ELSE 0 END status
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
STATE_WINDOW(
CASE WHEN voltage >= 205 and voltage <= 235 THEN 1 ELSE 0 END
)
SLIMIT 10;
```
以上 SQL查询超级表 meters 中,时间戳大于等于 2022-01-01T00:00:00+08:00且时间戳小于 2022-01-01T00:05:00+08:00的数据数据首先按照子表名 tbname 进行数据切分;根据电压是否在正常范围内进行状态窗口的划分;最后,取前 10 个分片的数据作为结果。查询结果如下:
```text
tbname | _wstart | _wend | _wduration | status |
=====================================================================================================================================
d76 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d47 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d37 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d87 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d64 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d35 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d83 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d51 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d63 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
d0 | 2021-12-31 16:00:00.000 | 2021-12-31 16:04:50.000 | 290000 | 0 |
Query OK, 10 row(s) in set (0.040495s)
```
### 会话窗口
会话窗口根据记录的时间戳主键的值来确定是否属于同一个会话。如下图所示,如果设置时间戳的连续的间隔小于等于 12 秒,则以下 6 条记录构成 2 个会话窗口,分别是:[2019-04-28 14:22:102019-04-28 14:22:30]和[2019-04-28 14:23:102019-04-28 14:23:30]。因为 2019-04-28 14:22:30 与 2019-04-28 14:23:10 之间的时间间隔是 40 秒超过了连续时间间隔12 秒)。
![会话窗口示意图](./session-window.png)
在 tol_value 时间间隔范围内的结果都认为归属于同一个窗口,如果连续的两条记录的时间超过 tol_val则自动开启下一个窗口。
```sql
SELECT COUNT(*), FIRST(ts) FROM temp_tb_1 SESSION(ts, tol_val);
```
示例:
```sql
SELECT tbname, _wstart, _wend, _wduration, count(*)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:10:00+08:00"
PARTITION BY tbname
SESSION(ts, 10m)
SLIMIT 10;
```
上面的 SQL查询超级表 meters 中,时间戳大于等于 2022-01-01T00:00:00+08:00且时间戳小于 2022-01-01T00:10:00+08:00的数据数据先按照子表名 tbname 进行数据切分,再根据 10 分钟的会话窗口进行切分;最后,取前 10 个分片的数据作为结果,返回子表名、窗口开始时间、窗口结束时间、窗口宽度、窗口内数据条数。查询结果如下:
```text
tbname | _wstart | _wend | _wduration | count(*) |
=====================================================================================================================================
d76 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d47 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d37 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d87 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d64 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d35 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d83 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d51 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d63 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
d0 | 2021-12-31 16:00:00.000 | 2021-12-31 16:09:50.000 | 590000 | 60 |
Query OK, 10 row(s) in set (0.043489s)
```
### 事件窗口
事件窗口根据开始条件和结束条件来划定窗口,当 start_trigger_condition 满足时则窗口开始,直到 end_trigger_condition 满足时窗口关闭。start_trigger_condition 和 end_trigger_condition 可以是任意 TDengine 支持的条件表达式,且可以包含不同的列。
事件窗口可以仅包含一条数据。即当一条数据同时满足 start_trigger_condition 和 end_trigger_condition且当前不在一个窗口内时这条数据自己构成了一个窗口。
事件窗口无法关闭时,不构成一个窗口,不会被输出。即有数据满足 start_trigger_condition此时窗口打开但后续数据都不能满足 end_trigger_condition这个窗口无法被关闭这部分数据不够成一个窗口不会被输出。
如果直接在超级表上进行事件窗口查询TDengine 会将超级表的数据汇总成一条时间线,然后进行事件窗口的计算。 如果需要对子查询的结果集进行事件窗口查询,那么子查询的结果集需要满足按时间线输出的要求,且可以输出有效的时间戳列。
以下面的 SQL 语句为例,事件窗口切分如下图所示。
```sql
select _wstart, _wend, count(*) from t event_window start with c1 > 0 end with c2 < 10
```
![事件窗口示意图](./event-window.png)
示例 SQL:
```sql
SELECT tbname, _wstart, _wend, _wduration, count(*)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:10:00+08:00"
PARTITION BY tbname
EVENT_WINDOW START WITH voltage >= 10 END WITH voltage < 20
LIMIT 10;
```
上面的 SQL查询超级表meters中时间戳大于等于2022-01-01T00:00:00+08:00且时间戳小于2022-01-01T00:10:00+08:00的数据数据先按照子表名tbname进行数据切分再根据事件窗口条件电压大于等于 10V且小于 20V 进行切分;最后,取前 10 行的数据作为结果,返回子表名、窗口开始时间、窗口结束时间、窗口宽度、窗口内数据条数。查询结果如下:
```text
tbname | _wstart | _wend | _wduration | count(*) |
=====================================================================================================================================
d0 | 2021-12-31 16:00:00.000 | 2021-12-31 16:00:00.000 | 0 | 1 |
d0 | 2021-12-31 16:00:30.000 | 2021-12-31 16:00:30.000 | 0 | 1 |
d0 | 2021-12-31 16:00:40.000 | 2021-12-31 16:00:40.000 | 0 | 1 |
d0 | 2021-12-31 16:01:20.000 | 2021-12-31 16:01:20.000 | 0 | 1 |
d0 | 2021-12-31 16:02:20.000 | 2021-12-31 16:02:20.000 | 0 | 1 |
d0 | 2021-12-31 16:02:30.000 | 2021-12-31 16:02:30.000 | 0 | 1 |
d0 | 2021-12-31 16:03:10.000 | 2021-12-31 16:03:10.000 | 0 | 1 |
d0 | 2021-12-31 16:03:30.000 | 2021-12-31 16:03:30.000 | 0 | 1 |
d0 | 2021-12-31 16:03:40.000 | 2021-12-31 16:03:40.000 | 0 | 1 |
d0 | 2021-12-31 16:03:50.000 | 2021-12-31 16:03:50.000 | 0 | 1 |
Query OK, 10 row(s) in set (0.034127s)
```
### 计数窗口
计数窗口是一种基于固定数据行数来划分窗口的方法。默认情况下,计数窗口首先将数据按照时间戳进行排序,然后根据 count_val 的值将数据划分为多个窗口,最后进行聚合计算。
count_val 表示每个计数窗口包含的最大数据行数。当总数据行数不能被 count_val 整除时,最后一个窗口的行数将小于 count_val。
sliding_val 是一个常量,表示窗口滑动的数量,类似于 interval 的滑动功能。通过调整 sliding_val你可以控制窗口之间重叠的程度从而实现对数据的细致分析。
以智能电表的数据模型为例,使用的查询 SQL 如下。
```sql
select _wstart, _wend, count(*)
from meters
where ts >= "2022-01-01T00:00:00+08:00" and ts < "2022-01-01T00:30:00+08:00"
count_window(10);
```
上面的 SQL 查询超级表 meters 中时间戳大于等于 2022-01-01T00:00:00+08:00 且时间戳小于 2022-01-01T00:10:00+08:00 的数据。以每 10 条数据为一组,返回每组的开始时间、结束时间和分组条数。查询结果如下。
```text
_wstart | _wend |count(*)|
===========================================================
2021-12-31 16:00:00.000 | 2021-12-31 16:10:00.000 | 10 |
2021-12-31 16:10:00.000 | 2021-12-31 16:20:00.000 | 10 |
2021-12-31 16:20:00.000 | 2021-12-31 16:30:00.000 | 10 |
```
## 时序数据特有函数
时序数据特有函数是 TDengine 针对时序数据查询场景专门设计的一组函数。在通用数据库中要实现类似的功能通常需要编写复杂的查询语句而且效率较低。为了降低用户的使用成本和简化查询过程TDengine 将这些功能以内置函数的形式提供,从而实现了高效且易于使用的时序数据处理能力。时序数据特有函数如下表所示。
| 函数 | 功能说明 |
|:---------------:|:--------------------------------------------------------------------:|
|CSUM | 累加和Cumulative sum忽略 NULL 值。 |
|DERIVATIVE | 统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒1signore_negative 参数的值可以是 0 或 1为 1 时表示忽略负值。 |
|DIFF | 统计表中某列的值与前一行对应值的差。 ignore_negative 取值为 0|1 可以不填,默认值为 0。 不忽略负值。ignore_negative 为 1 时表示忽略负数。|
|IRATE | 计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。 |
|MAVG | 计算连续 k 个值的移动平均数moving average。如果输入行数小于 k则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。|
|STATECOUNT | 返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1条件为 false 则重置为 -1如果数据为 NULL跳过该条数据。 |
|STATEDURATION | 返回满足某个条件的连续记录的时间长度,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加上两个记录之间的时间长度(第一个满足条件的记录时间长度记为 0条件为 false 则重置为 -1如果数据为 NULL跳过该条数据|
|TWA | 时间加权平均函数。统计表中某列在一段时间内的时间加权平均。 |
## 嵌套查询
嵌套查询,也称为 subquery子查询是指在一个 SQL 中内层查询的计算结果可以作为外层查询的计算对象来使用。TDengine 支持在 from 子句中使用非关联 subquery。非关联是指 subquery 不会用到父查询中的参数。在 select 查询的 from 子句之后,可以接一个独立的 select 语句,这个 select 语句被包含在英文圆括号内。通过使用嵌套查询你可以在一个查询中引用另一个查询的结果从而实现更复杂的数据处理和分析。以智能电表为例进行说明SQL 如下
```sql
SELECT max(voltage),*
FROM (
SELECT tbname,last_row(ts),voltage,current,phase,groupid,location
FROM meters
PARTITION BY tbname
)
GROUP BY groupid;
```
上面的 SQL 在内层查询中查询超级表 meters按照子表名进行分组每个子表查询最新一条数据外层查询将内层查询的结果作为输入按照 groupid 进行聚合,查询每组中的最大电压。
TDengine 的嵌套查询遵循以下规则:
1. 内层查询的返回结果将作为“虚拟表”供外层查询使用,此虚拟表建议起别名,以便于外层查询中方便引用。
2. 外层查询支持直接通过列名或列名的形式引用内层查询的列或伪列。
3. 在内层和外层查询中,都支持普通的表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。
4. 内层查询支持的功能特性与非嵌套的查询语句能力是一致的。内层查询的 ORDER BY 子句一般没有意义,建议避免这样的写法以免无谓的资源消耗。
5. 与非嵌套的查询语句相比,外层查询所能支持的功能特性存在如下限制:
6. 如果内层查询的结果数据未提供时间戳那么计算过程隐式依赖时间戳的函数在外层会无法正常工作。例如INTERP DERIVATIVE IRATE LAST_ROW FIRST LAST TWA STATEDURATION TAIL UNIQUE。
7. 如果内层查询的结果数据不是按时间戳有序那么计算过程依赖数据按时间有序的函数在外层会无法正常工作。例如LEASTSQUARES ELAPSED INTERP DERIVATIVE IRATE TWA DIFF STATECOUNT STATEDURATION CSUM MAVG TAIL UNIQUE。
8. 计算过程需要两遍扫描的函数在外层查询中无法正常工作。例如此类函数包括PERCENTILE。
## UNION 子句
TDengine 支持 UNION 操作符。也就是说,如果多个 SELECT 子句返回结果集的结构完全相同(列名、列类型、列数、顺序),那么可以通过 UNION 子句把这些结果集合并到一起。
示例:
```sql
(SELECT tbname,* FROM d1 limit 1)
UNION ALL
(SELECT tbname,* FROM d11 limit 2)
UNION ALL
(SELECT tbname,* FROM d21 limit 3);
```
上面的 SQL分别查询子表 d1 的 1 条数据,子表 d11 的 2 条数据,子表 d21 的 3 条数据,并将结果合并。返回的结果如下:
```text
tbname | ts | current | voltage | phase |
=================================================================================================
d11 | 2020-09-13 12:26:40.000 | 1.0260611 | 6 | 0.3620200 |
d11 | 2020-09-13 12:26:50.000 | 2.9544230 | 8 | 1.0048079 |
d21 | 2020-09-13 12:26:40.000 | 1.0260611 | 2 | 0.3520200 |
d21 | 2020-09-13 12:26:50.000 | 2.9544230 | 2 | 0.9948080 |
d21 | 2020-09-13 12:27:00.000 | -0.0000430 | 12 | 0.0099860 |
d1 | 2020-09-13 12:26:40.000 | 1.0260611 | 10 | 0.3520200 |
Query OK, 6 row(s) in set (0.006438s)
```
在同一个 sql 语句中,最多支持 100 个 UNION 子句。
## 关联查询
### Join 概念
1. 驱动表
在关联查询中,驱动表的角色取决于所使用的连接类型:在 Left Join 系列中,左表作为驱动表;而在 Right Join 系列中,右表作为驱动表。
2. 连接条件
在 TDengine 中连接条件是指进行表关联所指定的条件。对于所有关联查询除了ASOF Join 和 Window Join 以外),都需要指定连接条件,通常出现在 on 之后。在 ASOF Join 中,出现在 where 之后的条件也可以视作连接条件,而 Window Join 是通过 window_offset 来指定连接条件。
除了 ASOF Join 以外TDengine 支持的所有 Join 类型都必须显式指定连接条件。ASOF Join 因为默认定义了隐式的连接条件,所以在默认条件可以满足需求的情况下,可以不必显式指定连接条件。
对于除了 ASOF Join 和 Window Join 以外的其他类型的连接,连接条件中除了包含主连接条件以外,还可以包含任意多个其他连接条件。主连接条件与其他连接条件之间必须是 and 关系,而其他连接条件之间则没有这个限制。其他连接条件中可以包含主键列、标签列、普通列、常量及其标量函数或运算的任意逻辑运算组合。
以智能电表为例,下面这几条 SQL 都包含合法的连接条件。
```sql
select a.* from meters a left join meters b on a.ts = b.ts and a.ts > '2023-10-18 10:00:00.000'
select a.* from meters a left join meters b on a.ts = b.ts and (a.ts > '2023-10-18 10:00:00.000' or a.ts < '2023-10-17 10:00:00.000')
select a.* from meters a left join meters b on timetruncate(a.ts, 1s) = timetruncate(b.ts, 1s) and (a.ts + 1s > '2023-10-18 10:00:00.000' or a.groupId > 0)
select a.* from meters a left asof join meters b on timetruncate(a.ts, 1s) < timetruncate(b.ts, 1s) and a.groupId = b.groupId;
```
3. 主连接条件
作为一个时序数据库TDengine 的所有关联查询都围绕主键列进行。因此,对于除了 ASOF Join 和 Window Join 以外的所有关联查询都必须包含主键列的等值连接条件。在连接条件中首次出现的主键列等值连接条件将被视为主连接条件。ASOF Join 的主连接条件可以包含非等值的连接条件,而 Window Join 的主连接条件则是通过 window_offset 来指定的。
除了 Window Join 以外TDengine 支持在主连接条件中进行 timetruncate 函数操作,如 on timetruncate(a.ts, 1s) = timetruncate(b.ts, 1s)。除此以外,目前暂不支持其他函数及标量运算。
4. 分组条件
具有时序数据库特色的 ASOF Join、Window Join 支持先对关联查询的输入数据进行分组然后每个分组进行关联操作。分组只对关联查询的输入进行输出结果将不包含分组信息。ASOF Join、Window Join 中出现在 on 之后的等值条件ASOF Join 的主连接条件除外)将被作为分组条件。
5. 主键时间线
作为时序数据库 ,TDengine 要求每张表(子表)中必须有主键时间戳列,它将作为该表的主键时间线进行很多跟时间相关的运算,而在 subquery 的结果或者 Join 运算的结果中也需要明确哪一列将被视作主键时间线参与后续的与时间相关的运算。在 subquery 中,查询结果中存在的有序的第 1 个出现的主键列或其运算或等同主键列的伪列_wstart、_wend将被视作该输出表的主键时间线。Join 输出结果中主键时间线的选择遵从以下规则。
- Left Join、Right Join 系列中驱动表subquery的主键列将被作为后续查询的主键时间线。此外在 Window Join 窗口内,因为左右表同时有序,所以在窗口内可以把任意一张表的主键列作为主键时间线,优先选择本表的主键列为主键时间线。
- Inner Join 可以把任意一张表的主键列作为主键时间线,当存在类似分组条件(标签列的等值条件且与主连接条件是 and 关系)时将无法产生主键时间线。
- Full Join 因为无法产生任何一个有效的主键时间序列,所以没有主键时间线,这也就意味着 Full Join 中无法进行与时间线相关的运算。
### 语法说明
在接下来的内容中,我们将通过统一的方式并行介绍 Left Join 和 Right Join 系列。因此,在后续关于 Outer、Semi、Anti-Semi、ASOF、Window 等系列内容的介绍中,我们采用了“ Left/Right”这种表述方式来同时涵盖 Left Join 和 Right Join 的相关知识。这里的“ /”符号前的描述专指应用于 Left Join而“ /”符号后的描述则专指应用于 Right Join。通过这种表述方式我们可以更加清晰地展示这两种 Join 操作的特点和用法。
例如,当我们提及“左 / 右表”时,对于 Left Join它特指左表而对于 Right Join它则特指右表。同理当我们提及“右 / 左表”时,对于 Left Join它特指右表而对于 Right Join它则特指左表。
### Join 功能
下表列举了 TDengine 中所支持的 Join 类型和它们的定义。
| Join 类型 | 定义 |
|:------------------------:|:--------------------------------------------------------:|
|Inner Join | 内连接,只有左右表中同时符合连接条件的数据才会被返回,可以视为两张表符合连接条件的数据的交集 |
|Left/Right Outer Join | 左 / 右(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左 / 右表中不符合连接条件的数据集合 |
|Left/Right Semi Join | 左 / 右半连接,通常表达的是 in、exists 的含义,即对左 / 右表任意一条数据来说,只有当右 / 左表中存在任一符合连接条件的数据时才返回左 / 右表行数据 |
|Left/Right Anti-Semi Join | 左 / 右反连接,同左 / 右半连接的逻辑正好相反,通常表达的是 not in、not exists 的含义,即对左 / 右表任意一条数据来说,只有当右 / 左表中不存在任何符合连接条件的数据时才返回左 / 右表行数据 |
|left/Right ASOF Join | 左 / 右不完全匹配连接,不同于其他传统 Join 操作的完全匹配模式ASOF Join 允许以指定的匹配模式进行不完全匹配,即按照主键时间戳最接近的方式进行匹配 |
|Left/Right Window Join | 左 / 右窗口连接,根据左 / 右表中每一行的主键时间戳和窗口边界构造窗口并据此进行窗口连接,支持在窗口内进行投影、标量和聚合操作 |
|Full Outer Join | 全(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左右表中不符合连接条件的数据集合 |
### 约束和限制
1. 输入时间线限制
目前TDengine 中所有的 Join 操作都要求输入数据包含有效的主键时间线。对于所有表查询,这个要求通常可以满足。然而,对于 subquery则需要注意输出数据是否包
含有效的主键时间线。
2. 连接条件限制
连接条件的限制包括如下这些。
- 除了 ASOF Join 和 Window Join 以外,其他 Join 操作的连接条件中必须含主键列的主连接条件。
- 主连接条件与其他连接条件之间只支持 and 运算。
- 作为主连接条件的主键列只支持 timetruncate 函数运算,不支持其他函数和标量运算,作为其他连接条件时则无限制。
3. 分组条件限制
分组条件的限制包括如下这些。
- 只支持除了主键列以外的标签列、普通列的等值条件。
- 不支持标量运算。
- 支持多个分组条件,条件间只支持 and 运算。
4. 查询结果顺序限制
查询结果顺序的限制包括如下这些。
- 普通表、子表、subquery 且无分组条件无排序的场景下,查询结果会按照驱动表的主键列顺序输出。
- 由于超级表查询、Full Join 或有分组条件无排序的场景下,查询结果没有固定的输出顺序,因此,在有排序需求且输出无固定顺序的场景下,需要进行排序操作。部分依赖时间线的函数可能会因为没有有效的时间线输出而无法执行。

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@ -0,0 +1,5 @@
---
sidebar_label: 快速入门
title: TDengine 入门
toc_max_heading_level: 4
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/zh/05-basic/window.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@ -1,132 +0,0 @@
---
sidebar_label: Docker
title: 通过 Docker 快速体验 TDengine
description: 使用 Docker 快速体验 TDengine 的高效写入和查询
---
本节首先介绍如何通过 Docker 快速体验 TDengine然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker请使用[安装包的方式快速体验](../../get-started/package/)。如果您希望为 TDengine 贡献代码或对内部技术实现感兴趣,请参考 [TDengine GitHub 主页](https://github.com/taosdata/TDengine)下载源码构建和安装。
## 启动 TDengine
如果已经安装了 Docker首先拉取最新的 TDengine 容器镜像:
```shell
docker pull tdengine/tdengine:latest
```
或者指定版本的容器镜像:
```shell
docker pull tdengine/tdengine:3.0.1.4
```
然后只需执行下面的命令:
```shell
docker run -d -p 6030:6030 -p 6041:6041 -p 6043-6060:6043-6060 -p 6043-6060:6043-6060/udp tdengine/tdengine
```
注意TDengine 3.0 服务端仅使用 6030 TCP 端口。6041 为 taosAdapter 所使用提供 REST 服务端口。6043-6049 为 taosAdapter 提供第三方应用接入所使用端口,可根据需要选择是否打开。
如果需要将数据持久化到本机的某一个文件夹,则执行下边的命令:
```shell
docker run -d -v ~/data/taos/dnode/data:/var/lib/taos \
-v ~/data/taos/dnode/log:/var/log/taos \
-p 6030:6030 -p 6041:6041 -p 6043-6060:6043-6060 -p 6043-6060:6043-6060/udp tdengine/tdengine
```
:::note
- /var/lib/taos: TDengine 默认数据文件目录。可通过[配置文件]修改位置。你可以修改~/data/taos/dnode/data为你自己的数据目录
- /var/log/taos: TDengine 默认日志文件目录。可通过[配置文件]修改位置。你可以修改~/data/taos/dnode/log为你自己的日志目录
:::
确定该容器已经启动并且在正常运行。
```shell
docker ps
```
进入该容器并执行 `bash`
```shell
docker exec -it <container name> bash
```
然后就可以执行相关的 Linux 命令操作和访问 TDengine。
Docker 工具自身的下载和使用请参考 [Docker 官网文档](https://docs.docker.com/get-docker/)。
## TDengine 命令行界面
进入容器,执行 `taos`
```
$ taos
taos>
```
## TDengine 图形化界面
从 TDengine 3.3.0.0 开始TDengine docker image 中增加了一个新的 web 组件taos-explorer 可以使用它进行数据库、超级表、子表、数据的查看和管理。其上也有一些只在企业版中才提供的高级特性,如需要可联系 TDengine 销售团队。
使用 taos-explorer需要从浏览器访问其映射在主机上的端口假定主机名为 abc.com映射到主机的端口为 6060则需从浏览器访问 http://abc.com:6060. taos-explorer 默认在容器内使用 6060 端口。初次使用需要使用企业邮箱进行注册,注册后即可使用数据库中的用户名和密码登录。
## 体验写入速度
可以使用 TDengine 的自带工具 taosBenchmark 快速体验 TDengine 的写入速度。
启动 TDengine 的服务,在终端执行 `taosBenchmark`(曾命名为 `taosdemo`
```bash
$ taosBenchmark
```
该命令将在数据库 `test` 下面自动创建一张超级表 `meters`,该超级表下有 1 万张表,表名为 `d0``d9999`,每张表有 1 万条记录,每条记录有 `ts`、`current`、`voltage`、`phase` 四个字段,时间戳从 2017-07-14 10:40:00 000 到 2017-07-14 10:40:09 999每张表带有标签 `location``groupId`groupId 被设置为 1 到 10location 被设置为 `California.Campbell`、`California.Cupertino`、`California.LosAngeles`、`California.MountainView`、`California.PaloAlto`、`California.SanDiego`、`California.SanFrancisco`、`California.SanJose`、`California.SantaClara` 或者 `California.Sunnyvale`
这条命令很快完成 1 亿条记录的插入。具体时间取决于硬件性能,即使在一台普通的 PC 服务器往往也仅需十几秒。
taosBenchmark 命令本身带有很多选项,配置表的数目、记录条数等等,您可以设置不同参数进行体验,请执行 `taosBenchmark --help` 详细列出。taosBenchmark 详细使用方法请参照[如何使用 taosBenchmark 对 TDengine 进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)和 [taosBenchmark 参考手册](../../reference/taosbenchmark)。
## 体验查询速度
使用上述 `taosBenchmark` 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
查询超级表 `meters` 下的记录总条数:
```sql
SELECT COUNT(*) FROM test.meters;
```
查询 1 亿条记录的平均值、最大值、最小值等:
```sql
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
查询 location = "California.SanFrancisco" 的记录总条数:
```sql
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
查询 groupId = 10 的所有记录的平均值、最大值、最小值等:
```sql
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
对表 `d10` 按 10 每秒进行平均值、最大值和最小值聚合统计:
```sql
SELECT FIRST(ts), AVG(current), MAX(voltage), MIN(phase) FROM test.d10 INTERVAL(10s);
```
在上面的查询中你选择的是区间内的第一个时间戳ts另一种选择方式是 `\_wstart`,它将给出时间窗口的开始。关于窗口查询的更多信息,参见[特色查询](../../taos-sql/distinguished/)。
## 其它
更多关于在 Docker 环境下使用 TDengine 的细节,请参考 [用 Docker 部署 TDengine](../../deployment/docker)。

View File

@ -1,324 +0,0 @@
---
sidebar_label: 安装包
title: 使用安装包立即开始
description: 使用安装包快速体验 TDengine
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import PkgListV3 from "/components/PkgListV3";
您可以[用 Docker 立即体验](../../get-started/docker/) TDengine。如果您希望对 TDengine 贡献代码或对内部实现感兴趣,请参考我们的 [TDengine GitHub 主页](https://github.com/taosdata/TDengine) 下载源码构建和安装.
TDengine 完整的软件包包括服务端taosd、应用驱动taosc、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、命令行程序CLItaos和一些工具软件。目前 TDinsight 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../../reference/taosadapter/) 提供 [RESTful 接口](../../connector/rest-api/)。
为方便使用,标准的服务端安装包包含了 taosd、taosAdapter、taosc、taos、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,也可以仅下载 Lite 版本的安装包。
在 Linux 系统上TDengine 社区版提供 Deb 和 RPM 格式安装包,用户可以根据自己的运行环境选择合适的安装包。其中 Deb 支持 Debian/Ubuntu 及其衍生系统RPM 支持 CentOS/RHEL/SUSE 及其衍生系统。同时我们也为企业用户提供 tar.gz 格式安装包,也支持通过 `apt-get` 工具从线上进行安装。需要注意的是RPM 和 Deb 包不含 `taosdump` 和 TDinsight 安装脚本,这些工具需要通过安装 taosTools 包获得。TDengine 也提供 Windows x64 平台和 macOS x64/m1 平台的安装包。
## 运行环境要求
在linux系统中运行环境最低要求如下:
linux 内核版本 - 3.10.0-1160.83.1.el7.x86_64;
glibc 版本 - 2.17;
如果通过clone源码进行编译安装还需要满足:
cmake版本 - 3.26.4或以上;
gcc 版本 - 9.3.1或以上;
## 安装
**注意**
从TDengine 3.0.6.0 开始,不再提供单独的 taosTools 安装包,原 taosTools 安装包中包含的工具都在 TDengine-server 安装包中,如果需要请直接下载 TDengine -server 安装包。
<Tabs>
<TabItem label="Deb 安装" value="debinst">
1. 从列表中下载获得 Deb 安装包;
<PkgListV3 type={6}/>
2. 进入到安装包所在目录,执行如下的安装命令:
> 请将 `<version>` 替换为下载的安装包版本
```bash
sudo dpkg -i TDengine-server-<version>-Linux-x64.deb
```
</TabItem>
<TabItem label="RPM 安装" value="rpminst">
1. 从列表中下载获得 RPM 安装包;
<PkgListV3 type={5}/>
2. 进入到安装包所在目录,执行如下的安装命令:
> 请将 `<version>` 替换为下载的安装包版本
```bash
sudo rpm -ivh TDengine-server-<version>-Linux-x64.rpm
```
</TabItem>
<TabItem label="tar.gz 安装" value="tarinst">
1. 从列表中下载获得 tar.gz 安装包;
<PkgListV3 type={0}/>
2. 进入到安装包所在目录,使用 `tar` 解压安装包;
3. 进入到安装包所在目录,先解压文件后,进入子目录,执行其中的 install.sh 安装脚本。
> 请将 `<version>` 替换为下载的安装包版本
```bash
tar -zxvf TDengine-server-<version>-Linux-x64.tar.gz
```
解压文件后,进入相应子目录,执行其中的 `install.sh` 安装脚本:
```bash
sudo ./install.sh
```
:::info
install.sh 安装脚本在执行过程中,会通过命令行交互界面询问一些配置信息。如果希望采取无交互安装方式,那么可以运行 `./install.sh -e no`。运行 `./install.sh -h` 指令可以查看所有参数的详细说明信息。
:::
</TabItem>
<TabItem value="apt-get" label="apt-get">
可以使用 `apt-get` 工具从官方仓库安装。
**配置包仓库**
```bash
wget -qO - http://repos.taosdata.com/tdengine.key | sudo apt-key add -
echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-stable stable main" | sudo tee /etc/apt/sources.list.d/tdengine-stable.list
```
如果安装 Beta 版需要安装包仓库:
```bash
wget -qO - http://repos.taosdata.com/tdengine.key | sudo apt-key add -
echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-beta beta main" | sudo tee /etc/apt/sources.list.d/tdengine-beta.list
```
**使用 `apt-get` 命令安装**
```bash
sudo apt-get update
apt-cache policy tdengine
sudo apt-get install tdengine
```
:::tip
apt-get 方式只适用于 Debian 或 Ubuntu 系统。
:::
</TabItem>
<TabItem label="Windows 安装" value="windows">
**注意**
- 目前 TDengine 在 Windows 平台上只支持 Windows Server 2016/2019 和 Windows 10/11。
- 从 TDengine 3.1.0.0 开始,只提供 Windows 客户端安装包。如果需要 Windows 服务端安装包,请联系 TDengine 销售团队升级为企业版。
- Windows 上需要安装 VC 运行时库,可在此下载安装 [VC运行时库](https://learn.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redist?view=msvc-170), 如果已经安装此运行库可忽略。
按照以下步骤安装:
1. 从列表中下载获得 exe 安装程序;
<PkgListV3 type={3}/>
2. 运行可执行程序来安装 TDengine。
Note: 从 3.0.1.7 开始,只提供 TDengine 客户端的 Windows 客户端的下载。想要使用TDengine 服务端的 Windows 版本,请联系销售升级为企业版本。
</TabItem>
<TabItem label="macOS 安装" value="macos">
1. 从列表中下载获得 pkg 安装程序;
<PkgListV3 type={7}/>
2. 运行可执行程序来安装 TDengine。如果安装被阻止可以右键或者按 Ctrl 点击安装包,选择 `打开`
</TabItem>
</Tabs>
:::info
下载其他组件、最新 Beta 版及之前版本的安装包,请点击[发布历史页面](../../releases/tdengine)。
:::
:::note
当安装第一个节点时,出现 `Enter FQDN:` 提示的时候,不需要输入任何内容。只有当安装第二个或以后更多的节点时,才需要输入已有集群中任何一个可用节点的 FQDN支持该新节点加入集群。当然也可以不输入而是在新节点启动前配置到新节点的配置文件中。
:::
## 启动
<Tabs>
<TabItem label="Linux 系统" value="linux">
安装后,请使用 `systemctl` 命令来启动 TDengine 的服务进程。
```bash
systemctl start taosd
systemctl start taosadapter
systemctl start taoskeeper
systemctl start taos-explorer
```
你也可以直接运行 start-all.sh 脚本来启动上面的所有服务
```bash
start-all.sh
```
可以使用 systemctl 来单独管理上面的每一个服务
```bash
systemctl start taosd
systemctl stop taosd
systemctl restart taosd
systemctl status taosd
```
:::info
- `systemctl` 命令需要 _root_ 权限来运行,如果您非 _root_ 用户,请在命令前添加 `sudo`
- `systemctl stop taosd` 指令在执行后并不会马上停止 TDengine 服务,而是会等待系统中必要的落盘工作正常完成。在数据量很大的情况下,这可能会消耗较长时间。
- 如果系统中不支持 `systemd`,也可以用手动运行 `/usr/local/taos/bin/taosd` 方式启动 TDengine 服务。
:::
</TabItem>
<TabItem label="Windows 系统" value="windows">
安装后,可以在拥有管理员权限的 cmd 窗口执行 `sc start taosd` 或在 `C:\TDengine` 目录下,运行 `taosd.exe` 来启动 TDengine 服务进程。如需使用 http/REST 服务,请执行 `sc start taosadapter` 或运行 `taosadapter.exe` 来启动 taosAdapter 服务进程。
</TabItem>
<TabItem label="macOS 系统" value="macos">
安装后,在应用程序目录下,双击 TDengine 图标来启动程序,也可以运行 `sudo launchctl start ` 来启动 TDengine 服务进程。
```bash
sudo launchctl start com.tdengine.taosd
sudo launchctl start com.tdengine.taosadapter
sudo launchctl start com.tdengine.taoskeeper
sudo launchctl start com.tdengine.taos-explorer
```
你也可以直接运行 start-all.sh 脚本来启动上面的所有服务
```bash
start-all.sh
```
可以使用 `launchctl` 命令管理上面提到的每个 TDengine 服务,以下示例使用 `taosd`
```bash
sudo launchctl start com.tdengine.taosd
sudo launchctl stop com.tdengine.taosd
sudo launchctl list | grep taosd
sudo launchctl print system/com.tdengine.taosd
```
:::info
- `launchctl` 命令管理`com.tdengine.taosd`需要管理员权限,务必在前面加 `sudo` 来增强安全性。
- `sudo launchctl list | grep taosd` 指令返回的第一列是 `taosd` 程序的 PID若为 `-` 则说明 TDengine 服务未运行。
- 故障排查:
- 如果服务异常请查看系统日志 `launchd.log` 或者 `/var/log/taos` 目录下 `taosdlog` 日志获取更多信息。
:::
</TabItem>
</Tabs>
## TDengine 命令行CLI
为便于检查 TDengine 的状态执行数据库Database的各种即席Ad Hoc查询TDengine 提供一命令行应用程序(以下简称为 TDengine CLItaos。要进入 TDengine 命令行,您只要在终端执行 `taos` (Linux/Mac) 或 `taos.exe` (Windows) 即可。 TDengine CLI 的提示符号如下:
```cmd
taos>
```
在 TDengine CLI 中,用户可以通过 SQL 命令来创建/删除数据库、表等并进行数据库Database插入查询操作。在终端中运行的 SQL 语句需要以分号(;)结束来运行。示例:
```sql
CREATE DATABASE demo;
USE demo;
CREATE TABLE t (ts TIMESTAMP, speed INT);
INSERT INTO t VALUES ('2019-07-15 00:00:00', 10);
INSERT INTO t VALUES ('2019-07-15 01:00:00', 20);
SELECT * FROM t;
ts | speed |
========================================
2019-07-15 00:00:00.000 | 10 |
2019-07-15 01:00:00.000 | 20 |
Query OK, 2 row(s) in set (0.003128s)
```
除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。TDengine CLI 连同应用驱动也可以独立安装在机器上运行,更多细节请参考 [TDengine 命令行](../../reference/taos-shell/)。
## TDengine 图形化界面
从 TDengine 3.3.0.0 开始TDengine 发布包中增加了一个新的 web 组件taos-explorer 可以使用它进行数据库、超级表、子表、数据的查看和管理。其上也有一些只在企业版中才提供的高级特性,如需要可联系 TDengine 销售团队。
使用 taos-explorer需要从浏览器访问其映射在主机上的端口假定主机名为 abc.com映射到主机的端口为 6060则需从浏览器访问 http://abc.com:6060. taos-explorer 默认在容器内使用 6060 端口。初次使用需要使用企业邮箱进行注册,注册后即可使用数据库中的用户名和密码登录
## 使用 taosBenchmark 体验写入速度
可以使用 TDengine 的自带工具 taosBenchmark 快速体验 TDengine 的写入速度。
启动 TDengine 服务,然后在终端执行 `taosBenchmark`(曾命名为 `taosdemo`
```bash
$ taosBenchmark
```
该命令将在数据库 `test` 下面自动创建一张超级表 `meters`,该超级表下有 1 万张表,表名为 `d0``d9999`,每张表有 1 万条记录,每条记录有 `ts`、`current`、`voltage`、`phase` 四个字段,时间戳从 2017-07-14 10:40:00 000 到 2017-07-14 10:40:09 999每张表带有标签 `location``groupId`groupId 被设置为 1 到 10location 被设置为 `California.Campbell`、`California.Cupertino`、`California.LosAngeles`、`California.MountainView`、`California.PaloAlto`、`California.SanDiego`、`California.SanFrancisco`、`California.SanJose`、`California.SantaClara` 或者 `California.Sunnyvale`
这条命令很快完成 1 亿条记录的插入。具体时间取决于硬件性能,即使在一台普通的 PC 服务器往往也仅需十几秒。
taosBenchmark 命令本身带有很多选项,配置表的数目、记录条数等等,您可以设置不同参数进行体验,请执行 `taosBenchmark --help` 详细列出。taosBenchmark 详细使用方法请参照[如何使用 taosBenchmark 对 TDengine 进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)和 [taosBenchmark 参考手册](../../reference/taosbenchmark)。
## 使用 TDengine CLI 体验查询速度
使用上述 `taosBenchmark` 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
查询超级表 `meters` 下的记录总条数:
```sql
SELECT COUNT(*) FROM test.meters;
```
查询 1 亿条记录的平均值、最大值、最小值等:
```sql
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
查询 location = "California.SanFrancisco" 的记录总条数:
```sql
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
查询 groupId = 10 的所有记录的平均值、最大值、最小值等:
```sql
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
对表 `d10` 按每 10 秒进行平均值、最大值和最小值聚合统计:
```sql
SELECT FIRST(ts), AVG(current), MAX(voltage), MIN(phase) FROM test.d10 INTERVAL(10s);
```
在上面的查询中你选择的是区间内的第一个时间戳ts另一种选择方式是 `\_wstart`,它将给出时间窗口的开始。关于窗口查询的更多信息,参见[特色查询](../../taos-sql/distinguished/)。

View File

@ -1,26 +0,0 @@
可以使用 apt-get 工具从官方仓库安装。
**安装包仓库**
```
wget -qO - http://repos.taosdata.com/tdengine.key | sudo apt-key add -
echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-stable stable main" | sudo tee /etc/apt/sources.list.d/tdengine-stable.list
```
如果安装 Beta 版需要安装包仓库
```
echo "deb [arch=amd64] http://repos.taosdata.com/tdengine-beta beta main" | sudo tee /etc/apt/sources.list.d/tdengine-beta.list
```
**使用 apt-get 命令安装**
```
sudo apt-get update
apt-cache policy tdengine
sudo apt-get install tdengine
```
:::tip
apt-get 方式只适用于 Debian 或 Ubuntu 系统
::::

View File

@ -1 +0,0 @@
label: 立即开始

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,37 +0,0 @@
---
title: 立即开始
description: '快速设置 TDengine 环境并体验其高效写入和查询'
---
import xiaot from './xiaot.webp'
import xiaot_new from './xiaot-20231007.png'
import channel from './channel.webp'
import official_account from './official-account.webp'
TDengine 完整的软件包包括服务端taosd、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、应用驱动taosc、命令行程序 (CLItaos) 和一些工具软件。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../reference/taosadapter) 提供 [RESTful 接口](../connector/rest-api)。
本章主要介绍如何利用 Docker 或者安装包快速设置 TDengine 环境并体验其高效写入和查询。
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
<DocCardList items={useCurrentSidebarCategory().items}/>
```
## 加入 TDengine 官方社区
微信扫描以下二维码,学习了解 TDengine 的最新技术与大家共同交流物联网大数据技术应用、TDengine 使用问题和技巧等话题。
<table width="100%">
<tr align="center">
<td style={{padding:'1em 3em',border:0}}><img src={xiaot_new} alt="小 T 的二维码" width="200" /></td>
<td style={{padding:'1em 3em',border:0}}><img src={channel} alt="TDengine 微信视频号" width="200" /></td>
<td style={{padding:'1em 3em',border:0}}><img src={official_account} alt="TDengine 微信公众号" width="200" /></td>
</tr>
<tr align="center">
<td style={{padding:'1em 3em',border:0}}>加入 TDengine 微信群<br/>了解学习最新物联网技术</td>
<td style={{padding:'1em 3em',border:0}}>关注 TDengine 视频号<br/>收看技术直播与教学视频</td>
<td style={{padding:'1em 3em',border:0}}>关注 TDengine 公众号<br/>阅读技术文章与行业案例</td>
</tr>
</table>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,132 @@
---
sidebar_label: 数据订阅
title: 数据订阅
toc_max_heading_level: 4
---
为了满足应用程序实时获取 TDengine 写入的数据的需求或以事件到达顺序处理数据TDengine 提供了类似于消息队列产品的数据订阅和消费接口。在许多场景中采用TDengine 的时序大数据平台,无须再集成消息队列产品,从而简化应用程序设计并降低运维成本。
与 Kafka 类似,用户需要在 TDengine 中定义主题topic。然而TDengine 的主题可以是一个数据库、一张超级表,或者基于现有超级表、子表或普通表的查询条件,即一条查询语句。用户可以利用 SQL 对标签、表名、列、表达式等条件进行过滤,并对数据进行标量函数与 UDF 计算不包括数据聚合。与其他消息队列工具相比这是TDengine 数据订阅功能的最大优势。它提供了更高的灵活性数据的粒度由定义主题的SQL 决定,而且数据的过滤与预处理由 TDengine 自动完成,从而减少传输的数据量并降低应用程序的复杂度。
消费者订阅主题后可以实时接收最新的数据。多个消费者可以组成一个消费组共享消费进度实现多线程、分布式地消费数据提高消费速度。不同消费组的消费者即使消费同一个主题也不共享消费进度。一个消费者可以订阅多个主题。如果主题对应的是超级表或库数据可能会分布在多个不同的节点或数据分片上。当一个消费组中有多个消费者时可以提高消费效率。TDengine 的消息队列提供了消息的 ACKAcknowledgment确认也译作收到机制确保在宕机、重启等复杂环境下实现至少一次at least once消费。
为实现上述功能TDengine 会为预写数据日志Write-Ahead LoggingWAL文件自动创建索引以支持快速随机访问并提供了灵活可配置的文件切换与保留机制。用户可以根据需求指定 WAL 文件的保留时间和大小。通过这些方法WAL 被改造成一个保留事件到达顺序的、可持久化的存储引擎。对于以主题形式创建的查询TDengine 将从 WAL 读取数据。在消费过程中TDengine 根据当前消费进度从 WAL 直接读取数据,并使用统一的查询引擎实现过滤、变换等操作,然后将数据推送给消费者。
## 主题类型
TDengine 使用 SQL 创建的主题共有 3 种类型,下面分别介绍。
### 查询主题
订阅一条 SQL 查询的结果,本质上是连续查询,每次查询仅返回最新值,创建语法如下:
```sql
CREATE TOPIC [IF NOT EXISTS] topic_name as subquery
```
该 SQL 通过 SELECT 语句订阅(包括 SELECT *,或 SELECT ts, c1 等指定查询订阅,可以带条件过滤、标量函数计算,但不支持聚合函数、不支持时间窗口聚合)。需要注意的是:
1. 该类型 TOPIC 一旦创建则订阅数据的结构确定。
2. 被订阅或用于计算的列或标签不可被删除ALTER table DROP、修改ALTER table MODIFY
3. 若发生表结构变更,新增的列不出现在结果中。
4. 对于 select *,则订阅展开为创建时所有的列(子表、普通表为数据列,超级表为数据列加标签列)
假设需要订阅所有智能电表中电压值大于 200 的数据,而且仅仅返回时间戳、电流、电压 3 个采集量(不返回相位),那么可以通过下面的 SQL 创建 power_topic 这个主题。
```sql
CREATE TOPIC power_topic AS SELECT ts, current, voltage FROM power.meters WHERE voltage > 200;
```
### 超级表主题
订阅一个超级表中的所有数据,语法如下:
```sql
CREATE TOPIC [IF NOT EXISTS] topic_name [with meta] AS STABLE stb_name [where_condition]
```
与使用 `SELECT * from stbName` 订阅的区别是:
1. 不会限制用户的表结构变更,即表结构变更以及变更后的新数据都能够订阅到
2. 返回的是非结构化的数据,返回数据的结构会随着超级表的表结构变化而变化。
3. with meta 参数可选,选择时将返回创建超级表,子表等语句,主要用于 taosx 做超级表迁移。
4. where_condition 参数可选选择时将用来过滤符合条件的子表订阅这些子表。where 条件里不能有普通列,只能是 tag 或 tbnamewhere 条件里可以用函数,用来过滤 tag但是不能是聚合函数因为子表 tag 值无法做聚合。也可以是常量表达式,比如 2 > 1订阅全部子表或者 false订阅 0 个子表)。
5. 返回数据不包含标签。
### 数据库主题
订阅一个数据库里所有数据,其语法如下
```sql
CREATE TOPIC [IF NOT EXISTS] topic_name [with meta] AS DATABASE db_name;
```
通过该语句可创建一个包含数据库所有表数据的订阅
1. with meta 参数可选,选择时将返回数据库里所有超级表,子表、普通表的元数据创建、删除、修改语句,主要用于 taosx 做数据库迁移。
2. 超级表订阅和库订阅属于高级订阅模式,容易出错,如确实要使用,请咨询技术支持人员。
## 删除主题
如果不再需要订阅数据,可以删除 topic需要注意只有当前未在订阅中的 topic 才能被删除。
```sql
DROP TOPIC [IF EXISTS] topic_name;
```
## 查看主题
```sql
SHOW TOPICS;
```
上面的 SQL 会显示当前数据库下的所有主题的信息。
## 消费者
### 创建消费者
消费者的创建只能通过 TDengine 客户端驱动或者连接器所提供的 API 创建,详情可以参考开发指南或参考手册。
### 查看消费者
```sql
SHOW CONSUMERS;
```
显示当前数据库下所有消费者的信息,会显示消费者的状态,创建时间等信息。
### 删除消费组
消费者创建的时候,会给消费者指定一个消费者组,消费者不能显式的删除,但是消费者组在组内没有消费者时可以通过下面语句删除:
```sql
DROP CONSUMER GROUP [IF EXISTS] cgroup_name ON topic_name;
```
## 数据订阅
### 查看订阅信息
```sql
SHOW SUBSCRIPTIONS;
```
显示 topic 在不同 vgroup 上的消费信息,可用于查看消费进度。
### 订阅数据
TDengine 提供了全面且丰富的数据订阅 API旨在满足不同编程语言和框架下的数据订阅需求。这些接口包括但不限于创建消费者、订阅主题、取消订阅、获取实时数据、提交消费进度以及获取和设置消费进度等功能。目前TDengine 支持多种主流编程语言,包括 C、Java、Go、Rust、Python 和 C# 等,使得开发者能够轻松地在各种应用场景中使用 TDengine 的数据订阅功能。
值得一提的是TDengine 的数据订阅 API 与业界流行的 Kafka 订阅 API 保持了高度的一致性以便于开发者能够快速上手并利用现有的知识经验。为了方便用户了解和参考TDengine 的官方文档详细介绍了各种 API 的使用方法和示例代码具体内容可访问TDengine 官方网站的连接器部分。通过这些 API开发者可以高效地实现数据的实时订阅和处理从而满足各种复杂场景下的数据处理需求。
### 回放功能
TDengine 的数据订阅功能支持回放replay功能允许用户按照数据的实际写入时间顺序重新播放数据流。这一功能基于 TDengine 的高效 WAL 机制实现,确保了数据的一致性和可靠性。
要使用数据订阅的回放功能,用户可以在查询语句中指定时间范围,从而精确控制回放的起始时间和结束时间。这使得用户能够轻松地重放特定时间段内的数据,无论是为了故障排查、数据分析还是其他目的。
如果写入了如下 3 条数据,那么回放时则先返回第 1 条数据5s 后返回第 2 条数据,在获取第 2 条数据 3s 后返回第 3 条数据。
```text
2023/09/22 00:00:00.000
2023/09/22 00:00:05.000
2023/09/22 00:00:08.000
```
使用数据订阅的回放功能时需要注意如下几项。
- 数据订阅的回放功能仅查询订阅支持数据回放,超级表和库订阅不支持回放。
- 回放不支持进度保存。
- 因为数据回放本身需要处理时间,所以回放的精度存在几十毫秒的误差。

View File

@ -0,0 +1,122 @@
---
sidebar_label: 数据缓存
title: 数据缓存
toc_max_heading_level: 4
---
在工业互联网和物联网大数据应用场景中,时序数据库的性能表现尤为关键。这类应用程序不仅要求数据的实时写入能力,还需求能够迅速获取设备的最新状态或对最新数据进行实时计算。通常,大数据平台会通过部署 Redis 或类似的缓存技术来满足这些需求。然而,这种做法会增加系统的复杂性和运营成本。
为了解决这一问题TDengine 采用了针对性的缓存优化策略。通过精心设计的缓存机制TDengine 实现了数据的实时高效写入和快速查询,从而有效降低整个集群的复杂性和运营成本。这种优化不仅提升了性能,还为用户带来了更简洁、易用的解决方案,使他们能够更专注于核心业务的发展。
## 写缓存
TDengine 采用了一种创新的时间驱动缓存管理策略,亦称为写驱动的缓存管理机制。这一策略与传统的读驱动的缓存模式有所不同,其核心思想是将最新写入的数据优先保存在缓存中。当缓存容量达到预设的临界值时,系统会将最早存储的数据批量写入硬盘,从而实现缓存与硬盘之间的动态平衡。
在物联网数据应用中用户往往最关注最近产生的数据即设备的当前状态。TDengine 充分利用了这一业务特性,将最近到达的当前状态数据优先存储在缓存中,以便用户能够快速获取所需信息。
为了实现数据的分布式存储和高可用性TDengine 引入了虚拟节点vnode的概念。每个 vnode 可以拥有多达 3 个副本,这些副本共同组成一个 vnode group简称 vgroup。在创建数据库时用户需要确定每个 vnode 的写入缓存大小,以确保数据的合理分配和高效存储。
创建数据库时的两个关键参数—vgroups 和 buffer—分别决定了数据库中的数据由多少个 vgroup 进行处理,以及为每个 vnode 分配多少写入缓存。通过合理配置这两个
参数,用户可以根据实际需求调整数据库的性能和存储容量,从而实现最佳的性能和成本效益。
例 如, 下面的 SQL 创建了包含 10 个 vgroup每个 vnode 占 用 256MB 内存的数据库。
```ssql
create database power vgroups 10 buffer 256 cachemodel 'none' pages 128 pagesize 16
```
缓存越大越好,但超过一定阈值后再增加缓存对写入性能提升并无帮助。
## 读缓存
在创建数据库时,用户可以选择是否启用缓存机制以存储该数据库中每张子表的最新数据。这一缓存机制由数据库创建参数 cachemodel 进行控制。参数 cachemodel 具有如
下 4 种情况:
- none: 不缓存
- last_row: 缓存子表最近一行数据,这将显著改善 last_row 函数的性能
- last_value: 缓存子表每一列最近的非 NULL 值,这将显著改善无特殊影响(比如 WHERE ORDER BY GROUP BY INTERVAL时的 last 函数的性能
- both: 同时缓存最近的行和列,即等同于上述 cachemodel 值为 last_row 和 last_value 的行为同时生效
当使用数据库读缓存时,可以使用参数 cachesize 来配置每个 vnode 的内存大小。
- cachesize表示每个 vnode 中用于缓存子表最近数据的内存大小。默认为 1 ,范围是[1 65536],单位是 MB。需要根据机器内存合理配置。
## 元数据缓存
为了提升查询和写入操作的效率,每个 vnode 都配备了缓存机制,用于存储其曾经获取过的元数据。这一元数据缓存的大小由创建数据库时的两个参数 pages 和 pagesize 共同决定。其中pagesize 参数的单位是 KB用于指定每个缓存页的大小。如下 SQL 会为数据库 power 的每个 vnode 创建 128 个 page、每个 page 16KB 的元数据缓存
```sql
create database power pages 128 pagesize 16
```
## 文件系统缓存
TDengine 采用 WAL 技术作为基本的数据可靠性保障手段。WAL 是一种先进的数据保护机制,旨在确保在发生故障时能够迅速恢复数据。其核心原理在于,在数据实际写入数据存储层之前,先将其变更记录到一个日志文件中。这样一来,即便集群遭遇崩溃或其他故障,也能确保数据安全无损。
TDengine 利用这些日志文件实现故障前的状态恢复。在写入 WAL 的过程中,数据是以顺序追加的方式写入硬盘文件的。因此,文件系统缓存在此过程中发挥着关键作用,对写入性能产生显著影响。为了确保数据真正落盘,系统会调用 fsync 函数,该函数负责将文件系统缓存中的数据强制写入硬盘。
数据库参数 wal_level 和 wal_fsync_period 共同决定了 WAL 的保存行为。。
- wal_level此参数控制 WAL 的保存级别。级别 1 表示仅将数据写入 WAL但不立即执行 fsync 函数;级别 2 则表示在写入 WAL 的同时执行 fsync 函数。默认情况下wal_level 设为 1。虽然执行 fsync 函数可以提高数据的持久性,但相应地也会降低写入性能。
- wal_fsync_period当 wal_level 设置为 2 时,这个参数控制执行 fsync 的频率。设置为 0 表示每次写入后立即执行 fsync这可以确保数据的安全性但可能会牺牲一些性能。当设置为大于 0 的数值时,表示 fsync 周期,默认为 3000范围是[1 180000],单位毫秒。
```sql
create database power wal_level 1 wal_fsync_period 3000
```
在创建数据库时可以选择不同的参数类型,来选择性能优先或者可靠性优先。
- 1: 写 WAL 但不执行 fsync ,新写入 WAL 的数据保存在文件系统缓存中但并未写入磁盘,这种方式性能优先
- 2: 写 WAL 且执行 fsync新写入 WAL 的数据被立即同步到磁盘上,可靠性更高
## 实时数据查询的缓存实践
本节以智能电表为例,来详细看看 LAST 缓存对实时数据查询的性能提升。首先使用 taosBenchmark 工具,生成本章内容需要的智能电表的时序数据。
```shell
# taosBenchmark -d power -Q --start-timestamp=1600000000000 --tables=10000 --records=10000 --time-step=10000 -y
```
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的 电表数据库 power产生共 10 亿条时序数据。时序数据的时间戳从 `16000000000002020-09-13T20:26:40+08:00`开始,超级表为 `meter`s包含 10000 个设备(子表),每个设备有 10000 条数据,时序数据的采集频率是 10 秒/ 条。
查询任意一个电表的最新的电流和时间戳数据,执行如下 SQL
```sql
taos> select last(ts,current) from meters;
last(ts) | last(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.353815s)
taos> select last_row(ts,current) from meters;
last_row(ts) | last_row(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.344070s)
```
希望使用缓存来查询任意一个电表的最新时间戳数据,执行如下 SQL ,并检查数据库的缓存生效。
```sql
taos> alter database power cachemodel 'both' ;
Query OK, 0 row(s) affected (0.046092s)
taos> show create database power\G;
*************************** 1.row ***************************
Database: power
Create Database: CREATE DATABASE `power` BUFFER 256 CACHESIZE 1 CACHEMODEL 'both' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 2 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 10 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 3600 WAL_RETENTION_SIZE 0 KEEP_TIME_OFFSET 0
Query OK, 1 row(s) in set (0.000282s)
```
再次查询电表的最新的实时数据,第一次查询会做缓存计算,后续的查询时延就大大缩减。
```sql
taos> select last(ts,current) from meters;
last(ts) | last(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.044021s)
taos> select last_row(ts,current) from meters;
last_row(ts) | last_row(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.046682s)
```
可以看到查询的时延从 353/344ms 缩短到了 44ms提升约 8 倍。

View File

@ -0,0 +1,230 @@
---
sidebar_label: 流计算
title: 流计算
toc_max_heading_level: 4
---
在时序数据的处理中,经常要对原始数据进行清洗、预处理,再使用时序数据库进行长久的储存,而且经常还需要使用原始的时序数据通过计算生成新的时序数据。在传统的时序数据解决方案中,常常需要部署 Kafka、Flink 等流处理系统,而流处理系统的复杂性,带来了高昂的开发与运维成本。
TDengine 的流计算引擎提供了实时处理写入的数据流的能力,使用 SQL 定义实时流变换,当数据被写入流的源表后,数据会被以定义的方式自动处理,并根据定义的触发模式向目的表推送结果。它提供了替代复杂流处理系统的轻量级解决方案,并能够在高吞吐的数据写入的情况下,提供毫秒级的计算结果延迟。
流计算可以包含数据过滤,标量函数计算(含 UDF以及窗口聚合支持滑动窗口、会话窗口与状态窗口能够以超级表、子表、普通表为源表写入到目的超级表。在创建流时目的超级表将被自动创建随后新插入的数据会被流定义的方式处理并写入其中通过 partition by 子句,可以以表名或标签划分 partition不同的 partition 将写入到目的超级表的不同子表。
TDengine 的流计算能够支持分布在多个节点中的超级表聚合,能够处理乱序数据的写入。它提供 watermark 机制以度量容忍数据乱序的程度,并提供了 ignore expired 配置项以决定乱序数据的处理策略 —— 丢弃或者重新计算。
下面详细介绍流计算使用的具体方法。
## 创建流计算
语法如下:
```sql
CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name
[(field1_name, ...)] [TAGS (column_definition [, column_definition] ...)]
SUBTABLE(expression) AS subquery
stream_options: {
TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
WATERMARK time
IGNORE EXPIRED [0|1]
DELETE_MARK time
FILL_HISTORY [0|1]
IGNORE UPDATE [0|1]
}
column_definition:
col_name col_type [COMMENT 'string_value']
```
其中 subquery 是 select 普通查询语法的子集。
```sql
subquery: SELECT select_list
from_clause
[WHERE condition]
[PARTITION BY tag_list]
[window_clause]
window_cluse: {
SESSION(ts_col, tol_val)
| STATE_WINDOW(col)
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)]
| EVENT_WINDOW START WITH start_trigger_condition END WITH end_trigger_condition
| COUNT_WINDOW(count_val[, sliding_val])
}
```
subquery 支持会话窗口、状态窗口与滑动窗口。其中,会话窗口与状态窗口搭配超级表时必须与 partition by tbname 一起使用。
1. 其中SESSION 是会话窗口tol_val 是时间间隔的最大范围。在 tol_val 时间间隔范围内的数据都属于同一个窗口,如果连续的两条数据的时间间隔超过 tol_val则自动开启下一个窗口。
2. EVENT_WINDOW 是事件窗口,根据开始条件和结束条件来划定窗口。当 start_trigger_condition 满足时则窗口开始,直到 end_trigger_condition 满足时窗口关闭。 start_trigger_condition 和 end_trigger_condition 可以是任意 TDengine 支持的条件表达式,且可以包含不同的列。
3. COUNT_WINDOW 是计数窗口,按固定的数据行数来划分窗口。 count_val 是常量,是正整数,必须大于等于 2小于 2147483648。 count_val 表示每个 COUNT_WINDOW 包含的最大数据行数,总数据行数不能整除 count_val 时,最后一个窗口的行数会小于 count_val 。 sliding_val 是常量,表示窗口滑动的数量,类似于 INTERVAL 的 SLIDING 。
窗口的定义与时序数据窗口查询中的定义完全相同,具体可参考 TDengine 窗口函数部分。
如下 SQL 将创建一个流计算,执行后 TDengine 会自动创建名为avg_vol 的超级表,此流计算以 1min 为时间窗口、30s 为前向增量统计这些智能电表的平均电压,并将来自 meters 的数据的计算结果写入 avg_vol不同分区的数据会分别创建子表并写入不同子表。
```sql
CREATE STREAM avg_vol_s INTO avg_vol AS
SELECT _wstart, count(*), avg(voltage) FROM power.meters PARTITION BY tbname INTERVAL(1m) SLIDING(30s);
```
本节涉及的相关参数的说明如下。
- stb_name 是保存计算结果的超级表的表名,如果该超级表不存在,则会自动创建;如果已存在,则检查列的 schema 信息。详见 6.3.8 节。
- tags 子句定义了流计算中创建标签的规则。通过 tags 字段可以为每个分区对应的子表生成自定义的标签值。
## 流试计算的规则和策略
### 流计算的分区
在 TDengine 中,我们可以利用 partition by 子句结合 tbname、标签列、普通列或表达式对一个流进行多分区的计算。每个分区都拥有独立的时间线和时间窗口它们会分别进行数据聚合并将结果写入目的表的不同子表中。如果不使用 partition by 子句,所有数据将默认写入同一张子表中。
特别地partition by + tbname 是一种非常实用的操作,它表示对每张子表进行流计算。这样做的好处是可以针对每张子表的特点进行定制化处理,以提高计算效率。
在创建流时,如果不使用 substable 子句,流计算所创建的超级表将包含一个唯一的标签列 groupId。每个分区将被分配一个唯一的 groupId并通过 MD5 算法计算相应的子表名称。TDengine 将自动创建这些子表,以便存储各个分区的计算结果。这种机制使得数据管理更加灵活和高效,同时也方便后续的数据查询和分析。
若创建流的语句中包含 substable 子句,用户可以为每个分区对应的子表生成自定义的表名。示例如下。
```sql
CREATE STREAM avg_vol_s INTO avg_vol SUBTABLE(CONCAT('new-', tname)) AS SELECT _wstart, count(*), avg(voltage) FROM meters PARTITION BY tbname tname INTERVAL(1m);
```
PARTITION 子句中,为 tbname 定义了一个别名 tname 在 PARTITION 子句中的别名可以用于 SUBTABLE 子句中的表达式计算,在上述示例中,流新创建的子表规则为 new- + 子表名 + _超级表名 + _groupId。
**注意**:子表名的长度若超过 TDengine 的限制,将被截断。若要生成的子表名已经存在于另一超级表,由于 TDengine 的子表名是唯一的,因此对应新子表的创建以及数据的写入将会失败。
### 流计算处理历史数据
在正常情况下,流计算任务不会处理那些在流创建之前已经写入源表的数据。这是因为流计算的触发是基于新写入的数据,而非已有数据。然而,如果我们需要处理这些已有的历史数据,可以在创建流时设置 fill_history 选项为 1。
通过启用 fill_history 选项,创建的流计算任务将具备处理创建前、创建过程中以及创建后写入的数据的能力。这意味着,无论数据是在流创建之前还是之后写入的,都将纳入流计算的范围,从而确保数据的完整性和一致性。这一设置为用户提供了更大的灵活性,使其能够根据实际需求灵活处理历史数据和新数据。
比如,创建一个流,统计所有智能电表每 10s 产生的数据条数并且计算历史数据。SQL 如下:
```sql
create stream if not exists count_history_s fill_history 1 into count_history as select count(*) from power.meters interval(10s)
```
结合 fill_history 1 选项可以实现只处理特定历史时间范围的数据例如只处理某历史时刻2020 年 1 月 30 日)之后的数据。
```sql
create stream if not exists count_history_s fill_history 1 into count_history as select count(*) from power.meters where ts > '2020-01-30' interval(10s)
```
再如,仅处理某时间段内的数据,结束时间可以是未来时间。
```sql
create stream if not exists count_history_s fill_history 1 into count_history as select count(*) from power.meters where ts > '2020-01-30' and ts < '2023-01-01' interval(10s)
```
如果该流任务已经彻底过期,并且不再想让它检测或处理数据,您可以手动删除它,被计算出的数据仍会被保留。
### 流计算的触发模式
在创建流时,可以通过 TRIGGER 指令指定流计算的触发模式。对于非窗口计算,流计算的触发是实时的,对于窗口计算,目前提供 3 种触发模式,默认为 WINDOW_CLOSE。
1. AT_ONCE写入立即触发。
2. WINDOW_CLOSE窗口关闭时触发窗口关闭由事件时间决定可配合 watermark 使用)。
3. MAX_DELAY time若窗口关闭则触发计算。若窗口未关闭且未关闭时长超过 max delay 指定的时间,则触发计算。
窗口关闭是由事件时间决定的,如事件流中断、或持续延迟,此时事件时间无法更新,可能导致无法得到最新的计算结果。
因此,流计算提供了以事件时间结合处理时间计算的 MAX_DELAY 触发模式。MAX_DELAY 模式在窗口关闭时会立即触发计算。此外,当数据写入后,计算触发的时间超过 max delay 指定的时间,则立即触发计算。
### 流计算的窗口关闭
流计算的核心在于以事件时间(即写入记录中的时间戳主键)为基准来计算窗口的关闭时间,而不是依赖于 TDengine 服务器的时间。采用事件时间作为基准可以有效地规避客户端与服务器时间不一致所带来的问题,并且能够妥善解决数据乱序写入等挑战。
为了进一步控制数据乱序的容忍程度,流计算引入了 watermark 机制。在创建流时,用户可以通过 stream_option 参数指定 watermark 的值,该值定义了数据乱序的容忍上界,默认情况下为 0。
假设 T= 最新事件时间- watermark那么每次写入新数据时系统都会根据这个公式更新窗口的关闭时间。具体而言系统会将窗口结束时间小于 T 的所有打开的窗口关闭。如果触发模式设置为 window_close 或 max_delay则会推送窗口聚合的结果。下图展示了流计算的窗口关闭流程。
![流计算窗口关闭图解](./stream-window-close.png)
在上图中,纵轴表示时刻,横轴上的圆点表示已经收到的数据。相关流程说明如下。
1. T1 时刻,第 7 个数据点到达,根据 T = Latest event - watermark算出的时间在第二个窗口内所以第二个窗口没有关闭。
2. T2 时刻,第 6 和第 8 个数据点延迟到达 TDengine由于此时的 Latest event 没变T 也没变,乱序数据进入的第二个窗口还未被关闭,因此可以被正确处理。
3. T3 时刻,第 10 个数据点到达T 向后推移超过了第二个窗口关闭的时间,该窗口被关闭,乱序数据被正确处理。
在 window_close 或 max_delay 模式下,窗口关闭直接影响推送结果。在 at_once 模式下,窗口关闭只与内存占用有关。
### 过期数据处理策略
对于已关闭的窗口再次落入该窗口中的数据被标记为过期数据。TDengine 对于过期数据提供两种处理方式,由 IGNORE EXPIRED 选项指定。
1. 重新计算,即 IGNORE EXPIRED 0从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果
2. 直接丢弃,即 IGNORE EXPIRED 1默认配置忽略过期数据
无论在哪种模式下watermark 都应该被妥善设置,来得到正确结果(直接丢弃模式)或避免频繁触发重算带来的性能开销(重新计算模式)
### 数据更新的处理策略
TDengine 对于修改数据提供两种处理方式,由 IGNORE UPDATE 选项指定。
1. 检查数据是否被修改,即 IGNORE UPDATE 0默认配置如果被修改则重新计算对应窗口。
2. 不检查数据是否被修改,全部按增量数据计算,即 IGNORE UPDATE 1。
## 流计算的其它策略
### 写入已存在的超级表
当流计算结果需要写入已存在的超级表时,应确保 stb_name 列与 subquery 输出结果之间的对应关系正确。如果 stb_name 列与 subquery 输出结果的位置、数量完全匹配,那么不需要显式指定对应关系;如果数据类型不匹配,系统会自动将 subquery 输出结果的类型转换为对应的 stb_name 列的类型。
对于已经存在的超级表,系统会检查列的 schema 信息,确保它们与 subquery 输出结果相匹配。以下是一些关键点。
1. 检查列的 schema 信息是否匹配,对于不匹配的,则自动进行类型转换,当前只有数据长度大于 4096 bytes 时才报错,其余场景都能进行类型转换。
2. 检查列的个数是否相同,如果不同,需要显示的指定超级表与 subquery 的列的对应关系,否则报错。如果相同,可以指定对应关系,也可以不指定,不指定则按位置顺序对应。
**注意** 虽然流计算可以将结果写入已经存在的超级表,但不能让两个已经存在的流计算向同一张(超级)表中写入结果数据。这是为了避免数据冲突和不一致,确保数据的完整性和准确性。在实际应用中,应根据实际需求和数据结构合理设置列的对应关系,以实现高效、准确的数据处理。
### 自定义目标表的标签
用户可以为每个 partition 对应的子表生成自定义的 TAG 值,如下创建流的语句,
```sql
CREATE STREAM output_tag trigger at_once INTO output_tag_s TAGS(alias_tag varchar(100)) as select _wstart, count(*) from power.meters partition by concat("tag-", tbname) as alias_tag interval(10s));
```
在 PARTITION 子句中,为 concat"tag-" tbname定义了一个别名 alias_tag 对应超级表 output_tag_s 的自定义 TAG 的名字。在上述示例中,流新创建的子表的 TAG 将以前缀 'tag-' 连接原表名作为 TAG 的值。会对 TAG 信息进行如下检查。
1. 检查 tag 的 schema 信息是否匹配,对于不匹配的,则自动进行数据类型转换,当前只有数据长度大于 4096 bytes 时才报错,其余场景都能进行类型转换。
2. 检查 tag 的 个数是否相同,如果不同,需要显示的指定超级表与 subquery 的 tag 的对应关系,否则报错。如果相同,可以指定对应关系,也可以不指定,不指定则按位置顺序对应。
### 清理流计算的中间状态
```sql
DELETE_MARK time
```
DELETE_MARK 用于删除缓存的窗口状态,也就是删除流计算的中间结果。缓存的窗口状态主要用于过期数据导致的窗口结果更新操作。如果不设置,默认值是 10 年。
## 流计算的具体操作
### 删除流计算
仅删除流计算任务由流计算写入的数据不会被删除SQL 如下:
```sql
DROP STREAM [IF EXISTS] stream_name;
```
### 展示流计算
查看流计算任务的 SQL 如下:
```sql
SHOW STREAMS;
```
若要展示更详细的信息,可以使用
```sql
SELECT * from information_schema.`ins_streams`;
```
### 暂停流计算任务
暂停流计算任务的 SQL 如下:
```sql
PAUSE STREAM [IF EXISTS] stream_name;
```
没有指定 IF EXISTS如果该 stream 不存在,则报错。如果存在,则暂停流计算。指定了 IF EXISTS如果该 stream 不存在,则返回成功。如果存在,则暂停流计算。
### 恢复流计算任务
恢复流计算任务的 SQL 如下。如果指定了 ignore expired则恢复流计算任务时忽略流计算任务暂停期间写入的数据。
```sql
RESUME STREAM [IF EXISTS] [IGNORE UNTREATED] stream_name;
```
没有指定 IF EXISTS如果该 stream 不存在,则报错。如果存在,则恢复流计算。指定了 IF EXISTS如果 stream 不存在,则返回成功。如果存在,则恢复流计算。如果指定 IGNORE UNTREATED则恢复流计算时忽略流计算暂停期间写入的数据。

View File

@ -0,0 +1,52 @@
---
sidebar_label: 边云协同
title: 边云协同
toc_max_heading_level: 4
---
## 为什么需要边云协同
在工业互联网场景中,边缘设备只用来于处理局部数据,决策者无法只根据边缘设备采集的信息,形成对整个系统的全局认知。在实际应用中,边缘设备需要将数据上报给云计算平台(公有云或私有云),在云计算平台实现数据的汇聚与信息的融合,让决策者对整个数据有个全局的洞察。这种边云协同的架构,逐渐成为支撑工业互联网发展的重要支柱。
边缘设备主要是对生产线上的某一项或某几项数据,例如某个车间里的实时生产数据,进行监控和告警,然后将这些边缘侧的生产数据同步到位于云上大数据平台。
在边缘侧,对实时性的要求比较高,但其数据量可能并不大,一般一个生产车间的监测点数量,小到几千个,大到几万个。而在中心侧,往往计算资源比较充足,有能力将边缘侧的数据汇聚起来,进行分析计算。
要实现这一操作,对数据库或数据存储层的要求,就是要确保数据能够逐级上报,以及有选择地上报。在有些场景中,整体数据量非常大,因此必须要有选择地上报。例如,边缘侧一秒钟采集一次的原始记录,上报至中心侧时,降采样至一分钟一次,这种降采样极大地减少了数据量,但仍保留有关键信息,可用于长期数据的分析和预测。
在以前的工业数据采集流程中,数据是从工业逻辑控制器 PLC 中采集,然后进入 Historian即工业实时库再支撑业务应用。这种系统多采用主备架构不易水平扩展且严重依赖 Windows 生态,相对比较封闭。
## TDengine 的边云协同解决方案
TDengine Enterprise 致力于提供强大的边云协同能力,具备以下显著特性:
- 高效数据同步:支持每秒百万条数据的同步效率,确保数据在边缘侧和云端之间
快速、稳定地传输。
- 多数据源对接:兼容多种外部数据源,如 AVEVA PI System、OPC-UA、OPC-DA、MQTT 等,实现数据的广泛接入和整合。
- 灵活配置同步规则:提供可配置的同步规则,使用户能够根据实际需求自定义数据同步的策略和方式。
- 断线续传与重新订阅:支持断线续传和重新订阅功能,确保在网络不稳定或中断时数据同步的连续性和完整性。
- 历史数据迁移:支持历史数据的迁移,方便用户在升级或更换系统时,将历史数据无缝迁移到新系统中。
TDengine 的数据订阅功能为订阅方提供了极大的灵活性,允许用户根据需要配置订阅对象。用户可以订阅一个数据库、一张超级表,甚至是一个包含筛选条件的查询语句。这使得用户能够实现选择性的数据同步,将真正关心的数据(包括离线数据和乱序数据)从一个集群同步到另一个集群,以满足各种复杂场景下的数据需求。
下图以一个具体的生产车间的实例介绍了在 TDengine Enterprise 中实现边云协同架构。在生产车间,设备产生的实时数据存储至部署在边缘侧的 TDengine。部署在分厂的 TDengine 会去订阅生产车间的 TDengine 中的数据。为了更好地满足业务需求,需要由数据分析师设置一些订阅规则,例如将数据进行降采样,或者只同步超过指定阈值的数据。同理,部署在集团侧的 TDengine 再订阅来自各座分厂的数据,实现集团维度的数据汇聚后,即可进行下一步的分析和处理。
![边云协同示意图](./cloud-edge.png)
该实现思路主要有以下几点优势。
- 不需要一行代码,只须在边缘侧和云端进行简单配置即可。
- 数据跨区同步自动化程度大大提高,错误率降低。
- 数据无须缓存,减少批量发送,避免流量高峰阻塞带宽。
- 通过订阅方式同步数据,规则可配置,简单、灵活、实时性高。
- 边云均采用 TDengine数据模型完全统一降低数据治理难度。
制造业企业通常面临的一个痛点问题就是数据同步。很多企业目前采用离线方式来同步数据,但 TDengine Enterprise 实现了数据的实时同步,而且规则可配置。这种方式能够避免定期传输大数据量导致的资源浪费和带宽阻塞风险。
## 边云协同的优势
传统产业的 IT 和 OTOperational Technology运营技术建设状况各异相较于互联网行业大多数企业在数字化方面的投入明显滞后。许多企业仍在使用过时的系统处理数据而这些系统往往相互独立形成了所谓的数据孤岛。
在这样的背景下,要让 AI 为传统产业注入新的活力,首要任务是整合分散在各个角落的系统及其采集的数据,打破数据孤岛的限制。然而,这一过程充满挑战,因为涉及多种系统和繁多的工业互联网协议,数据汇聚并非简单的合并工作。它要求对来自不同数据源的数据进行清洗、加工和处理,以便将其整合到一个统一的平台上。
当所有数据汇聚于一个系统时,访问和处理数据的效率将得到显著提高。企业在应对实时数据时能够更迅速地做出反应,更有效地解决问题。企业内外的工作人员也能实现高效合作,提高整体运营效率。
此外,数据汇聚之后,可以利用先进的第三方 AI 分析工具进行更优质的异常监测、实时告警,并为产能、成本、设备维护等方面提供更精准的预测。这将使决策者能够更好地把握整体宏观情况,为企业的发展提供有力支持,助力传统产业实现数字化转型和智能化升级。

View File

@ -0,0 +1,58 @@
---
sidebar_label: 数据源接入
title: 零代码数据源接入
toc_max_heading_level: 4
---
TDengine Enterprise 配备了一个强大的可视化数据管理工具—taosExplorer。借助 taosExplorer用户只须在浏览器中简单配置就能轻松地向 TDengine 提交任务,实现以零代码方式将来自不同数据源的数据无缝导入 TDengine。在导入过程中TDengine 会对数据进行自动提取、过滤和转换以保证导入的数据质量。通过这种零代码数据源接入方式TDengine 成功转型为一个卓越的时序大数据汇聚平台。用户无须部署额外的 ETL 工具,从而大大简化整体架构的设计,提高了数据处理效率。
## 支持的数据源
目前 TDengine 支持的数据源如下:
1. Aveva PI System一个工业数据管理和分析平台前身为 OSIsoft PI System它能够实时采集、整合、分析和可视化工业数据助力企业实现智能化决策和精细化管理
2. Aveva Historian一个工业大数据分析软件前身为 Wonderware Historian专为工业环境设计用于存储、管理和分析来自各种工业设备、传感器的实时和历史数据。
3. OPC DA/UAOPC 是 Open Platform Communications 的缩写是一种开放式、标准化的通信协议用于不同厂商的自动化设备之间进行数据交换。它最初由微软公司开发旨在解决工业控制领域中不同设备之间互操作性差的问题。OPC 协议最初于 1996 年发布,当时称为 OPC DA Data Access主要用于实时数据采集和控制2006 年OPC 基金会发布了 OPC UA Unified Architecture 标准,它是一种基于服务的面向对象的协议,具有更高的灵活性和可扩展性,已成为 OPC 协议的主流版本。
4. MQTTMessage Queuing Telemetry Transport 的缩写,一种基于发布/订阅模式的轻量级通讯协议,专为低开销、低带宽占用的即时通讯设计,广泛适用于物联网、小型设备、移动应用等领域。
5. Kafka由 Apache 软件基金会开发的一个开源流处理平台,主要用于处理实时数据,并提供一个统一、高通量、低延迟的消息系统。它具备高速度、可伸缩性、持久性和分布式设计等特点,使得它能够在每秒处理数十万次的读写操作,支持上千个客户端,同时保持数据的可靠性和可用性。
6. OpenTSDB基于 HBase 的分布式、可伸缩的时序数据库。它主要用于存储、索引和提供从大规模集群(包括网络设备、操作系统、应用程序等)中收集的指标数据,使这些数据更易于访问和图形化展示。
7. CSVComma Separated Values 的缩写,是一种以逗号分隔的纯文本文件格式,通常用于电子表格或数据库软件。
8. TDengine 2泛指运行 TDengine 2.x 版本的 TDengine 实例。
9. TDengine 3泛指运行 TDengine 3.x 版本的 TDengine 实例。
10. MySQL PostgreSQL Oracle 等关系型数据库。
## 数据提取、过滤和转换
因为数据源可以有多个每个数据源的物理单位可能不一样命名规则也不一样时区也可能不同。为解决这个问题TDengine 内置 ETL 功能,可以从数据源的数据包中解析、提取需要的数据,并进行过滤和转换,以保证写入数据的质量,提供统一的命名空间。具体的功能如下:
1. 解析:使用 JSON Path 或正则表达式,从原始消息中解析字段
2. 从列中提取或拆分:使用 split 或正则表达式,从一个原始字段中提取多个字段
3. 过滤:只有表达式的值为 true 时,消息才会被写入 TDengine
4. 转换:建立解析后的字段和 TDengine 超级表字段之间的转换与映射关系。
下图展示了零代码接入平台的系统架构。
![零代码数据接入架构图](./data-in.png)
## 任务的创建
下面以 MQTT 数据源为例,介绍如何创建一个 MQTT 类型的任务,从 MQTT Broker 消费数据,并写入 TDengine。
1. 登录至 taosExplorer 以后,点击左侧导航栏上的“数据写入”,即可进入任务列表页面
2. 在任务列表页面,点击“+ 新增数据源”,即可进入任务创建页面
3. 输入任务名称后,选择类型为 MQTT 然后可以创建一个新的代理,或者选择已创建的代理
4. 输入 MQTT broker 的 IP 地址和端口号例如192.168.1.1001883
5. 配置认证和 SSL 加密:
- 如果 MQTT broker 开启了用户认证,则在认证部分,输入 MQTT broker 的用户名和密码;
- 如果 MQTT broker 开启了 SSL 加密,则可以打开页面上的 SSL 证书开关,并上传 CA 的证书,以及客户端的证书和私钥文件;
6. 在“采集配置“部分,可选择 MQTT 协议的版本,目前支持 3.1 3.1.1 5.0 三个版本;配置 Client ID 时要注意,如果对同一个 MQTT broker 创建了多个任务Client ID 应不同,否则会造成 Client ID 冲突,导致任务无法正常运行;在对主题和 QoS 进行配置时,需要使用 `<topic name>::<QoS>` 的形式,即订阅的主题与 QoS 之间要使用两个冒号分隔,其中 QoS 的取值范围为 0 1 2 分别代表 at most once at lease once exactly once配置完成以上信息后可以点击“检查连通性”按钮对以上配置进行检查如果连通性检查失败请按照页面上返回的具体错误提示进行修改
7. 在从 MQTT broker 同步数据的过程中taosX 还支持对消息体中的字段进行提取,过滤、映射等操作。在位于 “Payload 转换”下方的文本框中,可以直接输入输入消息体样例,或是以上传文件的方式导入,以后还会支持直接从所配置的服务器中检索样例消息;
8. 对消息体字段的提取,目前支持 2 种方式JSON 和正则表达式。对于简单的 key/value 格式的 JSON 数据,可以直接点击提取按钮,即可展示解析出的字段名;对于复杂的 JSON 数据,可以使用 JSON Path 提取感兴趣的字段;当使用正则表达式提取字段时,要保证正则表达式的正确性;
9. 消息体中的字段被解析后,可以基于解析出的字段名设置过滤规则,只有满足过滤规则的数据,才会写入 TDengine否则会忽略该消息例如可以配置过滤规则为 voltage > 200即只有当电压大于 200V 的数据才会被同步至 TDengine
10. 最后,在配置完消息体中的字段和超级表中的字段的映射规则后,就可以提交任务了;除了基本的映射以外,在这里还可以对消息中字段的值进行转换,例如:可以通过表达式 expr 将原消息体中的电压和电流,计算为功率后再写入 TDengine
11. 任务提交后,会自动返回任务列表页面,如果提交成功,任务的状态会切换至“运行中”,如果提交失败,可通过查看该任务的活动日志,查找错误原因;
12. 对于运行中的任务,点击指标的查看按钮,可以查看该任务的详细运行指标,弹出窗口划分为 2 个标签页,分别展示该任务多次运行的累计指标和本次运行的指标,这些指标每 2 秒钟会自动刷新一次。
## 任务管理
在任务列表页面,还可以对任务进行启动、停止、查看、删除、复制等操作,也可以查看各个任务的运行情况,包括写入的记录条数、流量等。

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,9 @@
---
sidebar_label: 高级功能
title: TDengine 高级功能
toc_max_heading_level: 4
---
TDengine 不仅是一个高性能、分布式的时序数据库核心产品,而且集成了专为时序数据量身定制的一系列功能,包括数据订阅、缓存、流计算和 ETL 等。这些功能共同构成了一个完整的时序数据处理解决方案。因此,当你选择使用 TDengine 时,你的应用程序无须额外集成 Kafka、Redis、Spark 或 Flink 等第三方工具从而极大地简化应用程序的设计复杂度并显著降低运维成本。下图直观地展示了传统大数据平台架构与TDengine 架构之间的异同点,突显了 TDengine 在时序数据处理领域的独特优势。
![传统大数据平台架构与 TDengine 架构的对比](./architecture-compare.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB