diff --git a/docs/zh/02-concept/index.md b/docs/zh/02-concept.md similarity index 100% rename from docs/zh/02-concept/index.md rename to docs/zh/02-concept.md diff --git a/docs/zh/03-intro/index.md b/docs/zh/03-intro.md similarity index 58% rename from docs/zh/03-intro/index.md rename to docs/zh/03-intro.md index a651cf438f..519c60cf66 100644 --- a/docs/zh/03-intro/index.md +++ b/docs/zh/03-intro.md @@ -73,3 +73,77 @@ TDengine 经过特别优化,以适应时间序列数据的独特需求,引 3. 简化系统架构带来的成本降低:作为一个极简的时序数据平台,TDengine 集成了消息队列、缓存、流计算等必要功能,避免了额外集成众多其他组件的需要。这 种简化的系统架构显著降低了系统的复杂度,从而减少了研发和运营成本,提高了整体运营效率。 +## 技术生态 + +在整个时序大数据平台中,TDengine 扮演的角色如下: + +
+ +![TDengine Database 技术生态图](eco_system.webp) + +
图 1. TDengine 技术生态图
+
+ +上图中,左侧是各种数据采集或消息队列,包括 OPC-UA、MQTT、Telegraf、也包括 Kafka,他们的数据将被源源不断的写入到 TDengine。右侧则是可视化、BI 工具、组态软件、应用程序。下侧则是 TDengine 自身提供的命令行程序(CLI)以及可视化管理工具。 + +## 典型适用场景 + +作为一个高性能、分布式、支持 SQL 的时序数据库(Time-series Database),TDengine 的典型适用场景包括但不限于 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) + diff --git a/docs/zh/04-get-started/01-install.md b/docs/zh/04-get-started/01-install.md index 3cf51596e8..76b4d7ee6a 100644 --- a/docs/zh/04-get-started/01-install.md +++ b/docs/zh/04-get-started/01-install.md @@ -17,6 +17,8 @@ TDengine 的安装包含括服务端(taosd)、应用驱动(taosc)、用 ## Linux 系统 +## 安装步骤 + 访问 TDengine 的官方版本发布页面:https://docs.taosdata.com/releases/tdengine/ ,下载 TDengine 安装包:TDengine-server-3.3.0.0-Linux-x64.tar.gz 。其他类型安装包的安装方法请参考相关文档,TDengine 遵循各种安装包的标准。 1. 进入到安装包所在目录,使用 tar 解压安装包 @@ -64,6 +66,34 @@ Active: inactive (dead) - 如果操作系统不支持 systemctl,可以通过手动运行 /usr/local/taos/bin/taosd 命令来启动 TDengine 服务。 +### 目录结构 + +安装 TDengine 后,默认会在操作系统中生成下列目录或文件: + +| 目录/文件 | 说明 | +| ------------------------- | -------------------------------------------------------------------- | +| /usr/local/taos/bin | TDengine 可执行文件目录。其中的执行文件都会软链接到/usr/bin 目录下。 | +| /usr/local/taos/driver | TDengine 动态链接库目录。会软链接到/usr/lib 目录下。 | +| /usr/local/taos/examples | TDengine 各种语言应用示例目录。 | +| /usr/local/taos/include | TDengine 对外提供的 C 语言接口的头文件。 | +| /etc/taos/taos.cfg | TDengine 默认[配置文件] | +| /var/lib/taos | TDengine 默认数据文件目录。可通过[配置文件]修改位置。 | +| /var/log/taos | TDengine 默认日志文件目录。可通过[配置文件]修改位置。 | + +### 可执行程序 + +TDengine 的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下。其中包括: + +- _taosd_:TDengine 服务端可执行文件 +- _taos_:TDengine Shell 可执行文件 +- _taosdump_:数据导入导出工具 +- _taosBenchmark_:TDengine 测试工具 +- _remove.sh_:卸载 TDengine 的脚本,请谨慎执行,链接到/usr/bin 目录下的**rmtaos**命令。会删除 TDengine 的安装目录/usr/local/taos,但会保留/etc/taos、/var/lib/taos、/var/log/taos +- _taosadapter_: 提供 RESTful 服务和接受其他多种软件写入请求的服务端可执行文件 +- _TDinsight.sh_:用于下载 TDinsight 并安装的脚本 +- _set_core.sh_:用于方便调试设置系统生成 core dump 文件的脚本 +- _taosd-dump-cfg.gdb_:用于方便调试 taosd 的 gdb 执行脚本。 + ## Docker 1. 测试机器如果已经安装了 Docker,首先拉取最新的 TDengine 容器镜像: diff --git a/docs/zh/05-basic/02-insert.md b/docs/zh/05-basic/02-insert.md index 34ddddcd30..0c7ffd86a4 100644 --- a/docs/zh/05-basic/02-insert.md +++ b/docs/zh/05-basic/02-insert.md @@ -132,4 +132,4 @@ INSERT INTO d1001 (ts, current) VALUES ("2018-10-03 14:38:05", 22); ```sql delete from meters where ts < '2021-10-01 10:40:00.100' ; -``` \ No newline at end of file +``` diff --git a/docs/zh/08-develop/01-connect/index.md b/docs/zh/08-develop/01-connect/index.md index 80a8431731..c89a92dfb6 100644 --- a/docs/zh/08-develop/01-connect/index.md +++ b/docs/zh/08-develop/01-connect/index.md @@ -1,6 +1,7 @@ --- title: 建立连接 -description: 使用连接器建立与 TDengine 的连接,以及连接器的安装和连接 +sidebar_label: 建立连接 +toc_max_heading_level: 4 --- import Tabs from "@theme/Tabs"; @@ -14,16 +15,16 @@ import ConnCSNative from "./_connect_cs.mdx"; import ConnC from "./_connect_c.mdx"; import ConnR from "./_connect_r.mdx"; import ConnPHP from "./_connect_php.mdx"; -import InstallOnLinux from "../../08-connector/_linux_install.mdx"; -import InstallOnWindows from "../../08-connector/_windows_install.mdx"; -import InstallOnMacOS from "../../08-connector/_macos_install.mdx"; -import VerifyLinux from "../../08-connector/_verify_linux.mdx"; -import VerifyMacOS from "../../08-connector/_verify_macos.mdx"; -import VerifyWindows from "../../08-connector/_verify_windows.mdx"; +import InstallOnLinux from "../../14-reference/05-connector/_linux_install.mdx"; +import InstallOnWindows from "../../14-reference/05-connector/_windows_install.mdx"; +import InstallOnMacOS from "../../14-reference/05-connector/_macos_install.mdx"; +import VerifyLinux from "../../14-reference/05-connector/_verify_linux.mdx"; +import VerifyMacOS from "../../14-reference/05-connector/_verify_macos.mdx"; +import VerifyWindows from "../../14-reference/05-connector/_verify_windows.mdx"; TDengine 提供了丰富的应用程序开发接口,为了便于用户快速开发自己的应用,TDengine 支持了多种编程语言的连接器,其中官方连接器包括支持 C/C++、Java、Python、Go、Node.js、C#、Rust、Lua(社区贡献)和 PHP (社区贡献)的连接器。这些连接器支持使用原生接口(taosc)和 REST 接口(部分语言暂不支持)连接 TDengine 集群。社区开发者也贡献了多个非官方连接器,例如 ADO.NET 连接器、Lua 连接器和 PHP 连接器。 -## 连接器建立连接的方式 +## 连接方式 连接器建立连接的方式,TDengine 提供三种: diff --git a/docs/zh/08-develop/02-model/_category_.yml b/docs/zh/08-develop/02-model/_category_.yml deleted file mode 100644 index e5dae7c27c..0000000000 --- a/docs/zh/08-develop/02-model/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -label: 数据建模 - diff --git a/docs/zh/08-develop/02-model/index.mdx b/docs/zh/08-develop/02-model/index.mdx deleted file mode 100644 index cc070e2e5f..0000000000 --- a/docs/zh/08-develop/02-model/index.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -sidebar_label: 数据建模 -title: TDengine 数据建模 -description: TDengine 中如何建立数据模型 ---- - -TDengine 采用类关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库、超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。 - -关于数据建模请参考[视频教程](https://www.taosdata.com/blog/2020/11/11/1945.html)。 - -## 创建库 - -不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能以最大效率工作,TDengine 建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除 SQL 标准的选项外,还可以指定保留时长、副本数、缓存大小、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如: - -```sql -CREATE DATABASE power KEEP 365 DURATION 10 BUFFER 16 WAL_LEVEL 1; -``` - -上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,每个 VNode 的写入内存池的大小为 16 MB,对该数据库入会写 WAL 但不执行 FSYNC。详细的语法及参数请见 [数据库管理](../../taos-sql/database) 章节。 - -创建库之后,需要使用 SQL 命令 `USE` 将当前库切换过来,例如: - -```sql -USE power; -``` - -将当前连接里操作的库换为 power,否则对具体表操作前,需要使用“库名.表名”来指定库的名字。 - -:::note - -- 任何一张表或超级表必须属于某个库,在创建表之前,必须先创建库。 -- 创建并插入记录、查询历史记录的时候,均需要指定时间戳。 - -::: - -## 创建超级表 - -一个物联网系统,往往存在多种类型的设备,比如对于电网,存在智能电表、变压器、母线、开关等等。为便于多表之间的聚合,使用 TDengine, 需要对每个类型的数据采集点创建一个超级表。以 [表 1](../../concept) 中的智能电表为例,可以使用如下的 SQL 命令创建超级表: - -```sql -CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int); -``` - -与创建普通表一样,创建超级表时,需要提供表名(示例中为 meters),表结构 Schema,即数据列的定义。第一列必须为时间戳(示例中为 ts),其他列为采集的物理量(示例中为 current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的 Schema (示例中为 location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组 ID、管理员 ID 等等。标签的 Schema 可以事后增加、删除、修改。具体定义以及细节请见 [TDengine SQL 的超级表管理](../../taos-sql/stable) 章节。 - -每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。对于电网,我们就需要对智能电表、变压器、母线、开关等都建立一个超级表。在物联网中,一个设备就可能有多个数据采集点(比如一台风力发电的风机,有的采集点采集电流、电压等电参数,有的采集点采集温度、湿度、风向等环境参数),这个时候,对这一类型的设备,需要建立多张超级表。 - -一张超级表最多容许 4096 列,如果一个采集点采集的物理量个数超过 4096,需要建多张超级表来处理。一个系统可以有多个 Database,一个 Database 里可以有一到多个超级表。 - -## 创建表 - -TDengine 对每个数据采集点需要独立建表。与标准的关系型数据库一样,一张表有表名,Schema,但除此之外,还可以带有一到多个标签。创建时,需要使用超级表做模板,同时指定标签的具体值。以 [表 1](../../concept) 中的智能电表为例,可以使用如下的 SQL 命令建表: - -```sql -CREATE TABLE d1001 USING meters TAGS ("California.SanFrancisco", 2); -``` - -其中 d1001 是表名,meters 是超级表的表名,后面紧跟标签 Location 的具体标签值为 "California.SanFrancisco",标签 groupId 的具体标签值为 2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 [TDengine SQL 的表管理](../../taos-sql/table) 章节。 - -TDengine 建议将数据采集点的全局唯一 ID 作为表名(比如设备序列号)。但对于有的场景,并没有唯一的 ID,可以将多个 ID 组合成一个唯一的 ID。不建议将具有唯一性的 ID 作为标签值。 - -### 自动建表 - -在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表且后面的 USING 语句被忽略。比如: - -```sql -INSERT INTO d1001 USING meters TAGS ("California.SanFrancisco", 2) VALUES (NOW, 10.2, 219, 0.32); -``` - -上述 SQL 语句将记录`(NOW, 10.2, 219, 0.32)`插入表 d1001。如果表 d1001 还未创建,则使用超级表 meters 做模板自动创建,同时打上标签值 `"California.SanFrancisco", 2`。 - -关于自动建表的详细语法请参见 [插入记录时自动建表](../../taos-sql/insert#插入记录时自动建表) 章节。 - -## 多列模型 vs 单列模型 - -TDengine 支持多列模型,只要物理量是一个数据采集点同时采集的(时间戳一致),这些量就可以作为不同列放在一张超级表里。但还有一种极限的设计,单列模型,每个采集的物理量都单独建表,因此每种类型的物理量都单独建立一超级表。比如电流、电压、相位,就建三张超级表。 - -TDengine 建议尽可能采用多列模型,因为插入效率以及存储效率更高。但对于有些场景,一个采集点的采集量的种类经常变化,这个时候,如果采用多列模型,就需要频繁修改超级表的结构定义,让应用变的复杂,这个时候,采用单列模型会显得更简单。 diff --git a/docs/zh/08-develop/02-sql.md b/docs/zh/08-develop/02-sql.md new file mode 100644 index 0000000000..647a5b728d --- /dev/null +++ b/docs/zh/08-develop/02-sql.md @@ -0,0 +1,106 @@ +--- +title: 执行 SQL +sidebar_label: 执行 SQL +toc_max_heading_level: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +上一节我们介绍了如何建立连接,本节以 WebSocket 连接为例,使用各种语言连接器执行 SQL 完成写入。 + +## 建库和表 + + + + +```java +// create statement +Statement stmt = conn.createStatement(); +// create database +stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS power"); +// use database +stmt.executeUpdate("USE power"); +// create table +stmt.executeUpdate("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))"); +``` + + + +## 插入数据 + + + + +```java +// insert data +String insertQuery = "INSERT INTO " + + "power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') " + + "VALUES " + + "(NOW + 1a, 10.30000, 219, 0.31000) " + + "(NOW + 2a, 12.60000, 218, 0.33000) " + + "(NOW + 3a, 12.30000, 221, 0.31000) " + + "power.d1002 USING power.meters TAGS(3, 'California.SanFrancisco') " + + "VALUES " + + "(NOW + 1a, 10.30000, 218, 0.25000) "; +int affectedRows = stmt.executeUpdate(insertQuery); +System.out.println("insert " + affectedRows + " rows."); +``` + + + +**Note** +NOW 为系统内部函数,默认为客户端所在计算机当前时间。 NOW + 1s 代表客户端当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒),s(秒),m(分),h(小时),d(天),w(周),n(月),y(年)。 + +## 查询数据 + + + + +```java +// query data +ResultSet resultSet = stmt.executeQuery("SELECT * FROM meters"); + +Timestamp ts; +float current; +String location; +while(resultSet.next()) { + ts = resultSet.getTimestamp(1); + current = resultSet.getFloat(2); + location = resultSet.getString("location"); + System.out.printf("%s, %f, %s\n", ts, current, location); +} +``` + + + +**Note** 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。 + +## 执行带有 reqId 的 SQL + +reqId 可用于请求链路追踪,reqId 就像分布式系统中的 traceId 作用一样。一个请求可能需要经过多个服务或者模块才能完成。reqId 用于标识和关联这个请求的所有相关操作,以便于我们可以追踪和分析请求的完整路径。 + +使用 reqId 有下面好处: +- 请求追踪:通过将同一个 reqId 关联到一个请求的所有相关操作,可以追踪请求在系统中的完整路径 +- 性能分析:通过分析一个请求的 reqId,可以了解请求在各个服务和模块中的处理时间,从而找出性能瓶颈 +- 故障诊断:当一个请求失败时,可以通过查看与该请求关联的 reqId 来找出问题发生的位置 + +如果用户不设置 reqId,连接器会在内部随机生成一个,但建议由显式用户设置以以更好地跟用户请求关联起来。 + + + + +```java +AbstractStatement aStmt = (AbstractStatement) connection.createStatement(); +aStmt.execute("CREATE DATABASE IF NOT EXISTS power", 1L); +aStmt.executeUpdate("USE power", 2L); +try (ResultSet rs = aStmt.executeQuery("SELECT * FROM meters limit 1", 3L)) { + while(rs.next()){ + Timestamp timestamp = rs.getTimestamp(1); + System.out.println("timestamp = " + timestamp); + } +} +aStmt.close(); +``` + + \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/01-sql-writing.mdx b/docs/zh/08-develop/03-insert-data/01-sql-writing.mdx deleted file mode 100644 index 49043495a8..0000000000 --- a/docs/zh/08-develop/03-insert-data/01-sql-writing.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: SQL 写入 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import JavaSQL from "./_java_sql.mdx"; -import JavaStmt from "./_java_stmt.mdx"; -import PySQL from "./_py_sql.mdx"; -import PyStmt from "./_py_stmt.mdx"; -import GoSQL from "./_go_sql.mdx"; -import GoStmt from "./_go_stmt.mdx"; -import RustSQL from "./_rust_sql.mdx"; -import RustStmt from "./_rust_stmt.mdx"; -import NodeSQL from "./_js_sql.mdx"; -import NodeStmt from "./_js_stmt.mdx"; -import CsSQL from "./_cs_sql.mdx"; -import CsStmt from "./_cs_stmt.mdx"; -import CSQL from "./_c_sql.mdx"; -import CStmt from "./_c_stmt.mdx"; -import PhpSQL from "./_php_sql.mdx"; -import PhpStmt from "./_php_stmt.mdx"; - -## SQL 写入简介 - -应用通过连接器执行 INSERT 语句来插入数据,用户还可以通过 TDengine CLI,手动输入 INSERT 语句插入数据。 - -### 一次写入一条 - -下面这条 INSERT 就将一条记录写入到表 d1001 中: - -```sql -INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31); -``` - -这里的`ts1`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](../../../taos-sql/insert) - -### 一次写入多条 - -TDengine 支持一次写入多条记录,比如下面这条命令就将两条记录写入到表 d1001 中: - -```sql -INSERT INTO d1001 VALUES (ts1, 10.2, 220, 0.23) (ts2, 10.3, 218, 0.25); -``` - -这里的`ts1`和`ts2`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](../../../taos-sql/insert) - -### 一次写入多表 - -TDengine 也支持一次向多个表写入数据,比如下面这条命令就向 d1001 写入两条记录,向 d1002 写入一条记录: - -```sql -INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31) (ts2, 12.6, 218, 0.33) d1002 VALUES (ts3, 12.3, 221, 0.31); -``` - -这里的`ts1`、`ts2`和`ts3`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](../../../taos-sql/insert) - -详细的 SQL INSERT 语法规则参考 [TDengine SQL 的数据写入](../../../taos-sql/insert)。 - -:::info - -- 要提高写入效率,需要批量写入。一般来说一批写入的记录条数越多,插入效率就越高。但一条记录不能超过 48KB,一条 SQL 语句总长度不能超过 1MB。 -- TDengine 支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开多个同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程频繁切换,会带来额外开销,合适的线程数量与服务端的处理能力,服务端的具体配置,数据库的参数,数据定义的 Schema,写入数据的 Batch Size 等很多因素相关。一般来说,服务端和客户端处理能力越强,所能支持的并发写入的线程可以越多;数据库配置时的 vgroups 参数值越多(但仍然要在服务端的处理能力以内)则所能支持的并发写入越多;数据定义的 Schema 越简单,所能支持的并发写入越多。 - -::: - -:::warning - -- 对同一张表,如果新插入记录的时间戳已经存在,则指定了新值的列会用新值覆盖旧值,而没有指定新值的列则不受影响。 -- 写入的数据的时间戳必须大于当前时间减去数据库配置参数 KEEP 的时间。如果 KEEP 配置为 3650 天,那么无法写入比 3650 天还早的数据。写入数据的时间戳也不能大于当前时间加配置参数 DURATION。如果 DURATION 为 2,那么无法写入比当前时间还晚 2 天的数据。 - -::: - -## 示例程序 - -### 普通 SQL 写入 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -:::note - -1. 无论 RESTful 方式建立连接还是本地驱动方式建立连接,以上示例代码都能正常工作。 -2. 唯一需要注意的是:由于 RESTful 接口无状态, 不能使用 `USE db;` 语句来切换数据库, 所以在上面示例中使用了`dbName.tbName`指定表名。 - -::: - -### 参数绑定写入 - -TDengine 也提供了支持参数绑定的 Prepare API,与 MySQL 类似,这些 API 目前也仅支持用问号 `?` 来代表待绑定的参数。在通过参数绑定接口写入数据时,就避免了 SQL 语法解析的资源消耗,从而在绝大多数情况下显著提升写入性能。 - -需要注意的是,只有使用原生连接的连接器,才能使用参数绑定功能。 - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/zh/08-develop/03-insert-data/20-kafka-writting.mdx b/docs/zh/08-develop/03-insert-data/20-kafka-writting.mdx deleted file mode 100644 index 4bd68b7faa..0000000000 --- a/docs/zh/08-develop/03-insert-data/20-kafka-writting.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: 从 Kafka 写入 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import PyKafka from "./_py_kafka.mdx"; - -## Kafka 介绍 - -Apache Kafka 是开源的分布式消息分发平台,被广泛应用于高性能数据管道、流式数据分析、数据集成和事件驱动类型的应用程序。Kafka 包含 Producer、Consumer 和 Topic,其中 Producer 是向 Kafka 发送消息的进程,Consumer 是从 Kafka 消费消息的进程。Kafka 相关概念可以参考[官方文档](https://kafka.apache.org/documentation/#gettingStarted)。 - - -### kafka topic - -Kafka 的消息按 topic 组织,每个 topic 会有一到多个 partition。可以通过 kafka 的 `kafka-topics` 管理 topic。 - -创建名为 `kafka-events` 的topic: - -``` -bin/kafka-topics.sh --create --topic kafka-events --bootstrap-server localhost:9092 -``` - -修改 `kafka-events` 的 partition 数量为 3: - -``` -bin/kafka-topics.sh --alter --topic kafka-events --partitions 3 --bootstrap-server=localhost:9092 -``` - -展示所有的 topic 和 partition: - -``` -bin/kafka-topics.sh --bootstrap-server=localhost:9092 --describe -``` - -## 写入 TDengine - -TDengine 支持 Sql 方式和 Schemaless 方式的数据写入,Sql 方式数据写入可以参考 [TDengine SQL 写入](../sql-writing/) 和 [TDengine 高效写入](../high-volume/)。Schemaless 方式数据写入可以参考 [TDengine Schemaless 写入](../../../reference/schemaless/) 文档。 - -## 示例代码 - - - - - - - diff --git a/docs/zh/08-develop/03-insert-data/30-influxdb-line.mdx b/docs/zh/08-develop/03-insert-data/30-influxdb-line.mdx deleted file mode 100644 index 4208cacb5d..0000000000 --- a/docs/zh/08-develop/03-insert-data/30-influxdb-line.mdx +++ /dev/null @@ -1,81 +0,0 @@ ---- -sidebar_label: InfluxDB 行协议 -title: InfluxDB 行协议 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import JavaLine from "./_java_line.mdx"; -import PyLine from "./_py_line.mdx"; -import GoLine from "./_go_line.mdx"; -import RustLine from "./_rust_line.mdx"; -import NodeLine from "./_js_line.mdx"; -import CsLine from "./_cs_line.mdx"; -import CLine from "./_c_line.mdx"; - -## 协议介绍 - -InfluxDB Line 协议采用一行字符串来表示一行数据。分为四部分: - -``` -measurement,tag_set field_set timestamp -``` - -- measurement 将作为超级表名。它与 tag_set 之间使用一个英文逗号来分隔。 -- tag_set 将作为标签数据,其格式形如 `=,=`,也即可以使用英文逗号来分隔多个标签数据。它与 field_set 之间使用一个半角空格来分隔。 -- field_set 将作为普通列数据,其格式形如 `=,=`,同样是使用英文逗号来分隔多个普通列的数据。它与 timestamp 之间使用一个半角空格来分隔。 -- timestamp 即本行数据对应的主键时间戳。 - -例如: - -``` -meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0.29 1648432611249500 -``` - -:::note - -- tag_set 中的所有的数据自动转化为 NCHAR 数据类型 -- field_set 中的每个数据项都需要对自身的数据类型进行描述, 比如 1.2f32 代表 FLOAT 类型的数值 1.2, 如果不带类型后缀会被当作 DOUBLE 处理 -- timestamp 支持多种时间精度。写入数据的时候需要用参数指定时间精度,支持从小时到纳秒的 6 种时间精度 -- 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常。(3.0.1.3 之后的版本 smlDataFormat 默认为 false,从3.0.3.0开始,该配置废弃) [TDengine 无模式写入参考指南](../../../reference/schemaless/#无模式写入行协议) -- 子表名生成规则 - - 默认产生的子表名是根据规则生成的唯一 ID 值。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlAutoChildTableNameDelimiter 参数来指定连接标签之间的分隔符,连接起来后作为子表名。举例如下:配置 smlAutoChildTableNameDelimiter=-, 插入数据为 st,t0=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1-4。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](../../../reference/schemaless/#无模式写入行协议) - -::: - -要了解更多可参考:[InfluxDB Line 协议官方文档](https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/) 和 [TDengine 无模式写入参考指南](../../../reference/schemaless/#无模式写入行协议) - -## 示例代码 - - - - - - - - - - - - - - - - - - - - - - -## SQL 查询示例 - -`meters` 是插入数据的超级表名。 - -可以通过超级表的 TAG 来过滤数据,比如查询 `location=California.LosAngeles,groupid=2` 可以通过如下 SQL: - -```sql -SELECT * FROM meters WHERE location = "California.LosAngeles" AND groupid = 2; -``` diff --git a/docs/zh/08-develop/03-insert-data/40-opentsdb-telnet.mdx b/docs/zh/08-develop/03-insert-data/40-opentsdb-telnet.mdx deleted file mode 100644 index 41b4069424..0000000000 --- a/docs/zh/08-develop/03-insert-data/40-opentsdb-telnet.mdx +++ /dev/null @@ -1,95 +0,0 @@ ---- -sidebar_label: OpenTSDB 行协议 -title: OpenTSDB 行协议 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import JavaTelnet from "./_java_opts_telnet.mdx"; -import PyTelnet from "./_py_opts_telnet.mdx"; -import GoTelnet from "./_go_opts_telnet.mdx"; -import RustTelnet from "./_rust_opts_telnet.mdx"; -import NodeTelnet from "./_js_opts_telnet.mdx"; -import CsTelnet from "./_cs_opts_telnet.mdx"; -import CTelnet from "./_c_opts_telnet.mdx"; - -## 协议介绍 - -OpenTSDB 行协议同样采用一行字符串来表示一行数据。OpenTSDB 采用的是单列模型,因此一行只能包含一个普通数据列。标签列依然可以有多个。分为四部分,具体格式约定如下: - -```txt - =[ =] -``` - -- metric 将作为超级表名; -- timestamp 本行数据对应的时间戳。根据时间戳的长度自动识别时间精度。支持秒和毫秒两种时间精度; -- value 度量值,必须为一个数值。对应的列名是 “\_value”; -- 最后一部分是标签集, 用空格分隔不同标签, 所有标签自动转化为 NCHAR 数据类型。 - -例如: - -```txt -meters.current 1648432611250 11.3 location=California.LosAngeles groupid=3 -``` -- 子表名生成规则 - - 默认产生的子表名是根据规则生成的唯一 ID 值。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlAutoChildTableNameDelimiter 参数来指定连接标签之间的分隔符,连接起来后作为子表名。举例如下:配置 smlAutoChildTableNameDelimiter=-, 插入数据为 st,t0=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1-4。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](../../../reference/schemaless/#无模式写入行协议) - - 参考 [OpenTSDB Telnet API 文档](http://opentsdb.net/docs/build/html/api_telnet/put.html)。 - -## 示例代码 - - - - - - - - - - - - - - - - - - - - - - -以上示例代码会自动创建 2 个超级表, 每个超级表有 4 条数据。 - -```cmd -taos> USE test; -Database changed. - -taos> SHOW STABLES; - name | -================================= - meters_current | - meters_voltage | -Query OK, 2 row(s) in set (0.002544s) - -taos> SELECT TBNAME, * FROM `meters_current`; - tbname | _ts | _value | groupid | location | -================================================================================================================================== - t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.249 | 10.800000000 | 3 | California.LosAngeles | - t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.250 | 11.300000000 | 3 | California.LosAngeles | - t_7e7b26dd860280242c6492a16... | 2022-03-28 09:56:51.249 | 10.300000000 | 2 | California.SanFrancisco | - t_7e7b26dd860280242c6492a16... | 2022-03-28 09:56:51.250 | 12.600000000 | 2 | California.SanFrancisco | -Query OK, 4 row(s) in set (0.005399s) -``` - -## SQL 查询示例 - -`meters_current` 是插入数据的超级表名。 - -可以通过超级表的 TAG 来过滤数据,比如查询 `location=California.LosAngeles groupid=3` 可以通过如下 SQL: - -```sql -SELECT * FROM `meters_current` WHERE location = "California.LosAngeles" AND groupid = 3; -``` diff --git a/docs/zh/08-develop/03-insert-data/50-opentsdb-json.mdx b/docs/zh/08-develop/03-insert-data/50-opentsdb-json.mdx deleted file mode 100644 index f6375dc3af..0000000000 --- a/docs/zh/08-develop/03-insert-data/50-opentsdb-json.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -sidebar_label: OpenTSDB JSON 格式协议 -title: OpenTSDB JSON 格式协议 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import JavaJson from "./_java_opts_json.mdx"; -import PyJson from "./_py_opts_json.mdx"; -import GoJson from "./_go_opts_json.mdx"; -import RustJson from "./_rust_opts_json.mdx"; -import NodeJson from "./_js_opts_json.mdx"; -import CsJson from "./_cs_opts_json.mdx"; -import CJson from "./_c_opts_json.mdx"; - -## 协议介绍 - -OpenTSDB JSON 格式协议采用一个 JSON 字符串表示一行或多行数据。例如: - -```json -[ - { - "metric": "sys.cpu.nice", - "timestamp": 1346846400, - "value": 18, - "tags": { - "host": "web01", - "dc": "lga" - } - }, - { - "metric": "sys.cpu.nice", - "timestamp": 1346846400, - "value": 9, - "tags": { - "host": "web02", - "dc": "lga" - } - } -] -``` - -与 OpenTSDB 行协议类似, metric 将作为超级表名, timestamp 表示时间戳,value 表示度量值, tags 表示标签集。 - -参考[OpenTSDB HTTP API 文档](http://opentsdb.net/docs/build/html/api_http/put.html)。 - -:::note - -- 对于 JSON 格式协议,TDengine 并不会自动把所有标签转成 NCHAR 类型, 字符串将将转为 NCHAR 类型, 数值将同样转换为 DOUBLE 类型。 -- 子表名生成规则 - - 默认产生的子表名是根据规则生成的唯一 ID 值。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlAutoChildTableNameDelimiter 参数来指定连接标签之间的分隔符,连接起来后作为子表名。举例如下:配置 smlAutoChildTableNameDelimiter=-, 插入数据为 st,t0=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1-4。 - - 用户也可以通过在client端的 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](../../../reference/schemaless/#无模式写入行协议) - -::: - -## 示例代码 - - - - - - - - - - - - - - - - - - - - - - -以上示例代码会自动创建 2 个超级表, 每个超级表有 2 条数据。 - -```cmd -taos> USE test; -Database changed. - -taos> SHOW STABLES; - name | -================================= - meters_current | - meters_voltage | -Query OK, 2 row(s) in set (0.001954s) - -taos> SELECT * FROM `meters.current`; - _ts | _value | groupid | location | -=================================================================================================================== - 2022-03-28 09:56:51.249 | 10.300000000 | 2.000000000 | California.SanFrancisco | - 2022-03-28 09:56:51.250 | 12.600000000 | 2.000000000 | California.SanFrancisco | -Query OK, 2 row(s) in set (0.004076s) -``` - -## SQL 查询示例 - -`meters_voltage` 是插入数据的超级表名。 - -可以通过超级表的 TAG 来过滤数据,比如查询 `location=California.LosAngeles groupid=1` 可以通过如下 SQL: - -```sql -SELECT * FROM `meters_current` WHERE location = "California.LosAngeles" AND groupid = 3; -``` diff --git a/docs/zh/08-develop/03-insert-data/_c_line.mdx b/docs/zh/08-develop/03-insert-data/_c_line.mdx deleted file mode 100644 index 7f2f0d5dd8..0000000000 --- a/docs/zh/08-develop/03-insert-data/_c_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/line_example.c:main}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_c_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_c_opts_json.mdx deleted file mode 100644 index 34b1d8ab3c..0000000000 --- a/docs/zh/08-develop/03-insert-data/_c_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/json_protocol_example.c:main}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_c_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_c_opts_telnet.mdx deleted file mode 100644 index 6bda068d12..0000000000 --- a/docs/zh/08-develop/03-insert-data/_c_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/telnet_line_example.c:main}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_c_sql.mdx b/docs/zh/08-develop/03-insert-data/_c_sql.mdx deleted file mode 100644 index 4e55c3387e..0000000000 --- a/docs/zh/08-develop/03-insert-data/_c_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/insert_example.c}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_c_stmt.mdx b/docs/zh/08-develop/03-insert-data/_c_stmt.mdx deleted file mode 100644 index 78f2d20dfb..0000000000 --- a/docs/zh/08-develop/03-insert-data/_c_stmt.mdx +++ /dev/null @@ -1,6 +0,0 @@ -```c title=一次绑定一行 -{{#include docs/examples/c/stmt_example.c}} -``` -```c title=一次绑定多行 72:117 -{{#include docs/examples/c/multi_bind_example.c}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_category_.yml b/docs/zh/08-develop/03-insert-data/_category_.yml deleted file mode 100644 index 430b3e4209..0000000000 --- a/docs/zh/08-develop/03-insert-data/_category_.yml +++ /dev/null @@ -1 +0,0 @@ -label: 写入数据 \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_cs_line.mdx b/docs/zh/08-develop/03-insert-data/_cs_line.mdx deleted file mode 100644 index ae49901c3a..0000000000 --- a/docs/zh/08-develop/03-insert-data/_cs_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/influxdbLine/Program.cs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_cs_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_cs_opts_json.mdx deleted file mode 100644 index 2627648616..0000000000 --- a/docs/zh/08-develop/03-insert-data/_cs_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/optsJSON/Program.cs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_cs_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_cs_opts_telnet.mdx deleted file mode 100644 index 660db13fd1..0000000000 --- a/docs/zh/08-develop/03-insert-data/_cs_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/optsTelnet/Program.cs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_cs_sql.mdx b/docs/zh/08-develop/03-insert-data/_cs_sql.mdx deleted file mode 100644 index 42a6bc4315..0000000000 --- a/docs/zh/08-develop/03-insert-data/_cs_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/sqlInsert/Program.cs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_cs_stmt.mdx b/docs/zh/08-develop/03-insert-data/_cs_stmt.mdx deleted file mode 100644 index d8d73ca15e..0000000000 --- a/docs/zh/08-develop/03-insert-data/_cs_stmt.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/stmtInsert/Program.cs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_go_line.mdx b/docs/zh/08-develop/03-insert-data/_go_line.mdx deleted file mode 100644 index df2afc0e87..0000000000 --- a/docs/zh/08-develop/03-insert-data/_go_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/insert/line/main.go}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_go_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_go_opts_json.mdx deleted file mode 100644 index 362ce43051..0000000000 --- a/docs/zh/08-develop/03-insert-data/_go_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/insert/json/main.go}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_go_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_go_opts_telnet.mdx deleted file mode 100644 index 518ea4c816..0000000000 --- a/docs/zh/08-develop/03-insert-data/_go_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/insert/telnet/main.go}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_go_sql.mdx b/docs/zh/08-develop/03-insert-data/_go_sql.mdx deleted file mode 100644 index 02f4d4e2ba..0000000000 --- a/docs/zh/08-develop/03-insert-data/_go_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/insert/sql/main.go}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_go_stmt.mdx b/docs/zh/08-develop/03-insert-data/_go_stmt.mdx deleted file mode 100644 index db4e227c43..0000000000 --- a/docs/zh/08-develop/03-insert-data/_go_stmt.mdx +++ /dev/null @@ -1,8 +0,0 @@ -```go -{{#include docs/examples/go/insert/stmt/main.go}} -``` - -:::tip -driver-go 的模块 `github.com/taosdata/driver-go/v3/wrapper` 是 C 接口的底层封装。使用这个模块也可以实现参数绑定写入。 - -::: diff --git a/docs/zh/08-develop/03-insert-data/_java_line.mdx b/docs/zh/08-develop/03-insert-data/_java_line.mdx deleted file mode 100644 index 17f759d30f..0000000000 --- a/docs/zh/08-develop/03-insert-data/_java_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/LineProtocolExample.java}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_java_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_java_opts_json.mdx deleted file mode 100644 index 1fc0adc202..0000000000 --- a/docs/zh/08-develop/03-insert-data/_java_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/JSONProtocolExample.java}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_java_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_java_opts_telnet.mdx deleted file mode 100644 index b68f54b4e8..0000000000 --- a/docs/zh/08-develop/03-insert-data/_java_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/TelnetLineProtocolExample.java}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_java_sql.mdx b/docs/zh/08-develop/03-insert-data/_java_sql.mdx deleted file mode 100644 index 636c7e00eb..0000000000 --- a/docs/zh/08-develop/03-insert-data/_java_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/RestInsertExample.java:insert}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_java_stmt.mdx b/docs/zh/08-develop/03-insert-data/_java_stmt.mdx deleted file mode 100644 index 2f6a337690..0000000000 --- a/docs/zh/08-develop/03-insert-data/_java_stmt.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/StmtInsertExample.java}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_js_line.mdx b/docs/zh/08-develop/03-insert-data/_js_line.mdx deleted file mode 100644 index cc138a76bd..0000000000 --- a/docs/zh/08-develop/03-insert-data/_js_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/influxdb_line_example.js}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_js_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_js_opts_json.mdx deleted file mode 100644 index cb3c275ce8..0000000000 --- a/docs/zh/08-develop/03-insert-data/_js_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/opentsdb_json_example.js}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_js_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_js_opts_telnet.mdx deleted file mode 100644 index db96742f31..0000000000 --- a/docs/zh/08-develop/03-insert-data/_js_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/opentsdb_telnet_example.js}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_js_sql.mdx b/docs/zh/08-develop/03-insert-data/_js_sql.mdx deleted file mode 100644 index a9a12f5d2c..0000000000 --- a/docs/zh/08-develop/03-insert-data/_js_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/insert_example.js}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_js_stmt.mdx b/docs/zh/08-develop/03-insert-data/_js_stmt.mdx deleted file mode 100644 index b94ae121c5..0000000000 --- a/docs/zh/08-develop/03-insert-data/_js_stmt.mdx +++ /dev/null @@ -1,12 +0,0 @@ -```js title=一次绑定一行 -{{#include docs/examples/node/nativeexample/param_bind_example.js}} -``` - -```js title=一次绑定多行 -{{#include docs/examples/node/nativeexample/multi_bind_example.js:insertData}} -``` - -:::info -一次绑定一行效率不如一次绑定多行,但支持非 INSERT 语句。一次绑定多行效率更高,但仅支持 INSERT 语句。 - -::: diff --git a/docs/zh/08-develop/03-insert-data/_php_sql.mdx b/docs/zh/08-develop/03-insert-data/_php_sql.mdx deleted file mode 100644 index 78cd663ec2..0000000000 --- a/docs/zh/08-develop/03-insert-data/_php_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```php -{{#include docs/examples/php/insert.php}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_php_stmt.mdx b/docs/zh/08-develop/03-insert-data/_php_stmt.mdx deleted file mode 100644 index 3bb7b2f8da..0000000000 --- a/docs/zh/08-develop/03-insert-data/_php_stmt.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```php -{{#include docs/examples/php/insert_stmt.php}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_py_kafka.mdx b/docs/zh/08-develop/03-insert-data/_py_kafka.mdx deleted file mode 100644 index d656325674..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_kafka.mdx +++ /dev/null @@ -1,124 +0,0 @@ -### python Kafka 客户端 - -Kafka 的 python 客户端可以参考文档 [kafka client](https://cwiki.apache.org/confluence/display/KAFKA/Clients#Clients-Python)。推荐使用 [confluent-kafka-python](https://github.com/confluentinc/confluent-kafka-python) 和 [kafka-python](http://github.com/dpkp/kafka-python)。以下示例以 [kafka-python](http://github.com/dpkp/kafka-python) 为例。 - -### 从 Kafka 消费数据 - -Kafka 客户端采用 pull 的方式从 Kafka 消费数据,可以采用单条消费的方式或批量消费的方式读取数据。使用 [kafka-python](http://github.com/dpkp/kafka-python) 客户端单条消费数据的示例如下: - -``` -from kafka import KafkaConsumer -consumer = KafkaConsumer('my_favorite_topic') -for msg in consumer: - print (msg) -``` - -单条消费的方式在数据流量大的情况下往往存在性能瓶颈,导致 Kafka 消息积压,更推荐使用批量消费的方式消费数据。使用 [kafka-python](http://github.com/dpkp/kafka-python) 客户端批量消费数据的示例如下: - -``` -from kafka import KafkaConsumer -consumer = KafkaConsumer('my_favorite_topic') -while True: - msgs = consumer.poll(timeout_ms=500, max_records=1000) - if msgs: - print (msgs) -``` - -### Python 多线程 - -为了提高数据写入效率,通常采用多线程的方式写入数据,可以使用 python 线程池 ThreadPoolExecutor 实现多线程。示例代码如下: - -``` -from concurrent.futures import ThreadPoolExecutor, Future -pool = ThreadPoolExecutor(max_workers=10) -pool.submit(...) -``` - -### Python 多进程 - -单个python进程不能充分发挥多核 CPU 的性能,有时候我们会选择多进程的方式。在多进程的情况下,需要注意,Kafka Consumer 的数量应该小于等于 Kafka Topic Partition 数量。Python 多进程示例代码如下: - -``` -from multiprocessing import Process - -ps = [] -for i in range(5): - p = Process(target=Consumer().consume()) - p.start() - ps.append(p) - -for p in ps: - p.join() -``` - -除了 Python 内置的多线程和多进程方式,还可以通过第三方库 gunicorn 实现并发。 - -### 完整示例 - -
-kafka_example_perform - -`kafka_example_perform` 是示例程序的入口 - -```py -{{#include docs/examples/python/kafka_example_perform.py}} -``` -
- -
-kafka_example_common - -`kafka_example_common` 是示例程序的公共代码 - -```py -{{#include docs/examples/python/kafka_example_common.py}} -``` -
- -
-kafka_example_producer - -`kafka_example_producer` 是示例程序的 producer 代码,负责生成并发送测试数据到 kafka - -```py -{{#include docs/examples/python/kafka_example_producer.py}} -``` -
- -
-kafka_example_consumer - -`kafka_example_consumer` 是示例程序的 consumer 代码,负责从 kafka 消费数据,并写入到 TDengine - -```py -{{#include docs/examples/python/kafka_example_consumer.py}} -``` -
- -### 执行步骤 - -
- 执行 Python 示例程序 - - 1. 安装并启动 kafka - - 2. python 环境准备 - - 安装 python3 - - 安装 taospy - - 安装 kafka-python - - 3. 执行示例程序 - - 程序的执行入口是 `kafka_example_perform.py`,获取程序完整的执行参数,请执行 help 命令。 - - ``` - python3 kafka_example_perform.py --help - ``` - - 以下为创建 100 个子表,每个子表 20000 条数据,kafka max poll 为 100,一个进程,每个进程一个处理线程的程序执行命令 - - ``` - python3 kafka_example_perform.py -table-count=100 -table-items=20000 -max-poll=100 -threads=1 -processes=1 - ``` - -
diff --git a/docs/zh/08-develop/03-insert-data/_py_line.mdx b/docs/zh/08-develop/03-insert-data/_py_line.mdx deleted file mode 100644 index 85f7e32e66..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_line.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```py -{{#include docs/examples/python/line_protocol_example.py}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_py_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_py_opts_json.mdx deleted file mode 100644 index 195c7090c0..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_opts_json.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```py -{{#include docs/examples/python/json_protocol_example.py}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_py_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_py_opts_telnet.mdx deleted file mode 100644 index 3bae1ea57b..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_opts_telnet.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```py -{{#include docs/examples/python/telnet_line_protocol_example.py}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_py_sql.mdx b/docs/zh/08-develop/03-insert-data/_py_sql.mdx deleted file mode 100644 index 1557e3994b..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```py -{{#include docs/examples/python/native_insert_example.py}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_py_stmt.mdx b/docs/zh/08-develop/03-insert-data/_py_stmt.mdx deleted file mode 100644 index e244288401..0000000000 --- a/docs/zh/08-develop/03-insert-data/_py_stmt.mdx +++ /dev/null @@ -1,12 +0,0 @@ -```py title=一次绑定一行 -{{#include docs/examples/python/bind_param_example.py}} -``` - -```py title=一次绑定多行 -{{#include docs/examples/python/multi_bind_example.py:bind_batch}} -``` - -:::info -一次绑定一行效率不如一次绑定多行,但支持非 INSERT 语句。一次绑定多行效率更高,但仅支持 INSERT 语句。 - -::: \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/_rust_line.mdx b/docs/zh/08-develop/03-insert-data/_rust_line.mdx deleted file mode 100644 index 25d322f8a7..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_line.mdx +++ /dev/null @@ -1,2 +0,0 @@ -```rust -``` diff --git a/docs/zh/08-develop/03-insert-data/_rust_opts_json.mdx b/docs/zh/08-develop/03-insert-data/_rust_opts_json.mdx deleted file mode 100644 index 25d322f8a7..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_opts_json.mdx +++ /dev/null @@ -1,2 +0,0 @@ -```rust -``` diff --git a/docs/zh/08-develop/03-insert-data/_rust_opts_telnet.mdx b/docs/zh/08-develop/03-insert-data/_rust_opts_telnet.mdx deleted file mode 100644 index 25d322f8a7..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_opts_telnet.mdx +++ /dev/null @@ -1,2 +0,0 @@ -```rust -``` diff --git a/docs/zh/08-develop/03-insert-data/_rust_schemaless.mdx b/docs/zh/08-develop/03-insert-data/_rust_schemaless.mdx deleted file mode 100644 index a26613bd15..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_schemaless.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```rust -{{#include docs/examples/rust/nativeexample/examples/schemaless_insert_line.rs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_rust_sql.mdx b/docs/zh/08-develop/03-insert-data/_rust_sql.mdx deleted file mode 100644 index fb59a48265..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_sql.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```rust -{{#include docs/examples/rust/restexample/examples/insert_example.rs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/_rust_stmt.mdx b/docs/zh/08-develop/03-insert-data/_rust_stmt.mdx deleted file mode 100644 index a889b56745..0000000000 --- a/docs/zh/08-develop/03-insert-data/_rust_stmt.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```rust -{{#include docs/examples/rust/nativeexample/examples/stmt_example.rs}} -``` diff --git a/docs/zh/08-develop/03-insert-data/index.md b/docs/zh/08-develop/03-insert-data/index.md deleted file mode 100644 index f1e5ada4df..0000000000 --- a/docs/zh/08-develop/03-insert-data/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -sidebar_label: 写入数据 -title: 写入数据 -description: TDengine 的各种写入方式 ---- - -TDengine 支持多种写入协议,包括 SQL,InfluxDB Line 协议, OpenTSDB Telnet 协议,OpenTSDB JSON 格式协议。数据可以单条插入,也可以批量插入,可以插入一个数据采集点的数据,也可以同时插入多个数据采集点的数据。同时,TDengine 支持多线程插入,支持时间乱序数据插入,也支持历史数据插入。InfluxDB Line 协议、OpenTSDB Telnet 协议和 OpenTSDB JSON 格式协议是 TDengine 支持的三种无模式写入协议。使用无模式方式写入无需提前创建超级表和子表,并且引擎能自适用数据对表结构做调整。 - -```mdx-code-block -import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; - - -``` \ No newline at end of file diff --git a/docs/zh/08-develop/04-query-data/_c.mdx b/docs/zh/08-develop/04-query-data/_c.mdx deleted file mode 100644 index c51557ef29..0000000000 --- a/docs/zh/08-develop/04-query-data/_c.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/query_example.c}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/04-query-data/_c_async.mdx b/docs/zh/08-develop/04-query-data/_c_async.mdx deleted file mode 100644 index 641a53e82d..0000000000 --- a/docs/zh/08-develop/04-query-data/_c_async.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```c -{{#include docs/examples/c/async_query_example.c:demo}} -``` \ No newline at end of file diff --git a/docs/zh/08-develop/04-query-data/_category_.yml b/docs/zh/08-develop/04-query-data/_category_.yml deleted file mode 100644 index 69273cb31c..0000000000 --- a/docs/zh/08-develop/04-query-data/_category_.yml +++ /dev/null @@ -1 +0,0 @@ -label: 查询数据 diff --git a/docs/zh/08-develop/04-query-data/_cs.mdx b/docs/zh/08-develop/04-query-data/_cs.mdx deleted file mode 100644 index 745ab36811..0000000000 --- a/docs/zh/08-develop/04-query-data/_cs.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```csharp -{{#include docs/examples/csharp/query/Program.cs}} -``` diff --git a/docs/zh/08-develop/04-query-data/_go.mdx b/docs/zh/08-develop/04-query-data/_go.mdx deleted file mode 100644 index b43894a1eb..0000000000 --- a/docs/zh/08-develop/04-query-data/_go.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/query/sync/main.go}} -``` diff --git a/docs/zh/08-develop/04-query-data/_go_async.mdx b/docs/zh/08-develop/04-query-data/_go_async.mdx deleted file mode 100644 index 3fbc6f5b6d..0000000000 --- a/docs/zh/08-develop/04-query-data/_go_async.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/go/query/async/main.go}} -``` diff --git a/docs/zh/08-develop/04-query-data/_java.mdx b/docs/zh/08-develop/04-query-data/_java.mdx deleted file mode 100644 index 74de32658c..0000000000 --- a/docs/zh/08-develop/04-query-data/_java.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```java -{{#include docs/examples/java/src/main/java/com/taos/example/RestQueryExample.java}} -``` diff --git a/docs/zh/08-develop/04-query-data/_js.mdx b/docs/zh/08-develop/04-query-data/_js.mdx deleted file mode 100644 index 5883d378e7..0000000000 --- a/docs/zh/08-develop/04-query-data/_js.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/query_example.js}} -``` diff --git a/docs/zh/08-develop/04-query-data/_js_async.mdx b/docs/zh/08-develop/04-query-data/_js_async.mdx deleted file mode 100644 index 4b0f54a034..0000000000 --- a/docs/zh/08-develop/04-query-data/_js_async.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```js -{{#include docs/examples/node/nativeexample/async_query_example.js}} -``` diff --git a/docs/zh/08-develop/04-query-data/_php.mdx b/docs/zh/08-develop/04-query-data/_php.mdx deleted file mode 100644 index bcafd1cfbc..0000000000 --- a/docs/zh/08-develop/04-query-data/_php.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```go -{{#include docs/examples/php/query.php}} -``` diff --git a/docs/zh/08-develop/04-query-data/_py.mdx b/docs/zh/08-develop/04-query-data/_py.mdx deleted file mode 100644 index 7184c66b8e..0000000000 --- a/docs/zh/08-develop/04-query-data/_py.mdx +++ /dev/null @@ -1,11 +0,0 @@ -通过迭代逐行获取查询结果。 - -```py -{{#include docs/examples/python/query_example.py:iter}} -``` - -一次获取所有查询结果,并把每一行转化为一个字典返回。 - -```py -{{#include docs/examples/python/query_example.py:fetch_all}} -``` diff --git a/docs/zh/08-develop/04-query-data/_py_async.mdx b/docs/zh/08-develop/04-query-data/_py_async.mdx deleted file mode 100644 index dd323ef364..0000000000 --- a/docs/zh/08-develop/04-query-data/_py_async.mdx +++ /dev/null @@ -1,8 +0,0 @@ -```py -{{#include docs/examples/python/async_query_example.py}} -``` - -:::note -这个示例程序,目前在 Windows 系统上还无法运行 - -::: diff --git a/docs/zh/08-develop/04-query-data/_rust.mdx b/docs/zh/08-develop/04-query-data/_rust.mdx deleted file mode 100644 index cab1b403fb..0000000000 --- a/docs/zh/08-develop/04-query-data/_rust.mdx +++ /dev/null @@ -1,3 +0,0 @@ -```rust -{{#include docs/examples/rust/restexample/examples/query_example.rs}} -``` diff --git a/docs/zh/08-develop/04-query-data/index.mdx b/docs/zh/08-develop/04-query-data/index.mdx deleted file mode 100644 index 52fd70653e..0000000000 --- a/docs/zh/08-develop/04-query-data/index.mdx +++ /dev/null @@ -1,180 +0,0 @@ ---- -sidebar_label: 查询数据 -title: 查询数据 -description: "主要查询功能,通过连接器执行同步查询和异步查询" ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import JavaQuery from "./_java.mdx"; -import PyQuery from "./_py.mdx"; -import GoQuery from "./_go.mdx"; -import RustQuery from "./_rust.mdx"; -import NodeQuery from "./_js.mdx"; -import CsQuery from "./_cs.mdx"; -import CQuery from "./_c.mdx"; -import PhpQuery from "./_php.mdx"; -import PyAsync from "./_py_async.mdx"; -import NodeAsync from "./_js_async.mdx"; -import CAsync from "./_c_async.mdx"; - -## 主要查询功能 - -TDengine 采用 SQL 作为查询语言。应用程序可以通过 REST API 或连接器发送 SQL 语句,用户还可以通过 TDengine 命令行工具 taos 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能: - -- 单列、多列数据查询 -- 标签和数值的多种过滤条件:>, \<, =, \<>, like 等 -- 聚合结果的分组(Group by)、排序(Order by)、约束输出(Limit/Offset) -- 时间窗口(Interval)、会话窗口(Session)和状态窗口(State_window)等窗口切分聚合查询 -- 数值列及聚合结果的四则运算 -- 时间戳对齐的连接查询(Join Query: 隐式连接)操作 -- 多种聚合/计算函数: count, max, min, avg, sum, twa, stddev, leastsquares, top, bottom, first, last, percentile, apercentile, last_row, spread, diff 等 - -例如:在命令行工具 taos 中,从表 d1001 中查询出 voltage > 215 的记录,按时间降序排列,仅仅输出 2 条。 - -```sql -taos> select * from d1001 where voltage > 215 order by ts desc limit 2; - ts | current | voltage | phase | -====================================================================================== - 2018-10-03 14:38:16.800 | 12.30000 | 221 | 0.31000 | - 2018-10-03 14:38:15.000 | 12.60000 | 218 | 0.33000 | -Query OK, 2 row(s) in set (0.001100s) -``` - -为满足物联网场景的需求,TDengine 支持几个特殊的函数,比如 twa(时间加权平均),spread (最大值与最小值的差),last_row(最后一条记录)等,更多与物联网场景相关的函数将添加进来。 - -具体的查询语法请看 [TDengine SQL 的数据查询](../../taos-sql/select) 章节。 - -## 多表聚合查询 - -物联网场景中,往往同一个类型的数据采集点有多个。TDengine 采用超级表(STable)的概念来描述某一个类型的数据采集点,一张普通的表来描述一个具体的数据采集点。同时 TDengine 使用标签来描述数据采集点的静态属性,一个具体的数据采集点有具体的标签值。通过指定标签的过滤条件,TDengine 提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样。 - -### 示例一 - -在 TDengine CLI,查找加利福尼亚州所有智能电表采集的电压平均值,并按照 location 分组。 - -``` -taos> SELECT AVG(voltage), location FROM meters GROUP BY location; - avg(voltage) | location | -=============================================================================================== - 219.200000000 | California.SanFrancisco | - 221.666666667 | California.LosAngeles | -Query OK, 2 rows in database (0.005995s) -``` - -### 示例二 - -在 TDengine CLI, 查找 groupId 为 2 的所有智能电表的记录条数,电流的最大值。 - -``` -taos> SELECT count(*), max(current) FROM meters where groupId = 2; - cunt(*) | max(current) | -================================== - 5 | 13.4 | -Query OK, 1 row(s) in set (0.002136s) -``` - -在 [TDengine SQL 的数据查询](../../taos-sql/select) 一章,查询类操作都会注明是否支持超级表。 - -## 降采样查询、插值 - -物联网场景里,经常需要通过降采样(down sampling)将采集的数据按时间段进行聚合。TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单。比如,将智能电表 d1001 采集的电流值每 10 秒钟求和 - -``` -taos> SELECT _wstart, sum(current) FROM d1001 INTERVAL(10s); - _wstart | sum(current) | -====================================================== - 2018-10-03 14:38:00.000 | 10.300000191 | - 2018-10-03 14:38:10.000 | 24.900000572 | -Query OK, 2 rows in database (0.003139s) -``` - -降采样操作也适用于超级表,比如:将加利福尼亚州所有智能电表采集的电流值每秒钟求和 - -``` -taos> SELECT _wstart, SUM(current) FROM meters where location like "California%" INTERVAL(1s); - _wstart | sum(current) | -====================================================== - 2018-10-03 14:38:04.000 | 10.199999809 | - 2018-10-03 14:38:05.000 | 23.699999809 | - 2018-10-03 14:38:06.000 | 11.500000000 | - 2018-10-03 14:38:15.000 | 12.600000381 | - 2018-10-03 14:38:16.000 | 34.400000572 | -Query OK, 5 rows in database (0.007413s) -``` - -降采样操作也支持时间偏移,比如:将所有智能电表采集的电流值每秒钟求和,但要求每个时间窗口从 500 毫秒开始 - -``` -taos> SELECT _wstart, SUM(current) FROM meters INTERVAL(1s, 500a); - _wstart | sum(current) | -====================================================== - 2018-10-03 14:38:03.500 | 10.199999809 | - 2018-10-03 14:38:04.500 | 10.300000191 | - 2018-10-03 14:38:05.500 | 13.399999619 | - 2018-10-03 14:38:06.500 | 11.500000000 | - 2018-10-03 14:38:14.500 | 12.600000381 | - 2018-10-03 14:38:16.500 | 34.400000572 | -Query OK, 6 rows in database (0.005515s) -``` - -物联网场景里,每个数据采集点采集数据的时间是难同步的,但很多分析算法(比如 FFT)需要把采集的数据严格按照时间等间隔的对齐,在很多系统里,需要应用自己写程序来处理,但使用 TDengine 的降采样操作就轻松解决。 - -如果一个时间间隔里,没有采集的数据,TDengine 还提供插值计算的功能。 - -语法规则细节请见 [TDengine SQL 的按时间窗口切分聚合](../../taos-sql/distinguished) 章节。 - -## 示例代码 - -### 查询数据 - -在 [SQL 写入](../insert-data/sql-writing) 一章,我们创建了 power 数据库,并向 meters 表写入了一些数据,以下示例代码展示如何查询这个表的数据。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -:::note - -1. 无论是使用 REST 连接还是原生连接的连接器,以上示例代码都能正常工作。 -2. 唯一需要注意的是:由于 REST 接口无状态, 不能使用 `use db` 语句来切换数据库。除了在 REST 参数中指定数据库以外也可以在 SQL 语句中使用 \.\ 来指定数据库。 - -::: - -### 异步查询 - -除同步查询 API 之外,TDengine 还提供性能更高的异步调用 API 处理数据插入、查询操作。在软硬件环境相同的情况下,异步 API 处理数据插入的速度比同步 API 快 2-4 倍。异步 API 采用非阻塞式的调用方式,在系统真正完成某个具体数据库操作前,立即返回。调用的线程可以去处理其他工作,从而可以提升整个应用的性能。异步 API 在网络延迟严重的情况下,优点尤为突出。 - -需要注意的是,只有使用原生连接的连接器,才能使用异步查询功能。 - - - - - - - - - diff --git a/docs/zh/08-develop/04-schemaless.md b/docs/zh/08-develop/04-schemaless.md new file mode 100644 index 0000000000..5fb2f852df --- /dev/null +++ b/docs/zh/08-develop/04-schemaless.md @@ -0,0 +1,218 @@ +--- +title: 无模式写入 +sidebar_label: 无模式写入 +toc_max_heading_level: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +在物联网应用中,为了实现自动化管理、业务分析和设备监控等多种功能,通常需要采集大量的数据项。然而,由于应用逻辑的版本升级和设备自身的硬件调整等原因,数据采集项可能会频繁发生变化。为了应对这种挑战,TDengine 提供了无模式(schemaless)写入方式,旨在简化数据记录过程。 + +采用无模式写入方式,用户无须预先创建超级表或子表,因为 TDengine 会根据实际写入的数据自动创建相应的存储结构。此外,在必要时,无模式写入方式还能自动添加必要的数据列或标签列,确保用户写入的数据能够被正确存储。 + +值得注意的是,通过无模式写入方式创建的超级表及其对应的子表与通过 SQL 直接创建的超级表和子表在功能上没有区别,用户仍然可以使用 SQL 直接向其中写入数据。然而,由于无模式写入方式生成的表名是基于标签值按照固定的映射规则生成的,因此这些表名可能缺乏可读性,不易于理解。 + +**采用无模式写入方式时会自动创建表,无须手动创建表。** + +## 无模式写入行协议 + +TDengine 的无模式写入行协议兼容 InfluxDB 的行协议、OpenTSDB 的 telnet 行协议和 OpenTSDB 的 JSON 格式协议。InfluxDB、OpenTSDB 的标准写入协议请参考各自的官方文档。 + +下面首先以 InfluxDB 的行协议为基础,介绍 TDengine 扩展的协议内容。该协议允许用户采用更加精细的方式控制(超级表)模式。采用一个字符串来表达一个数据行,可以向写入 API 中一次传入多行字符串来实现多个数据行的批量写入,其格式约定如下。 + +```text +measurement,tag_set field_set timestamp +``` + +各参数说明如下。 +- measurement 为数据表名,与 tag_set 之间使用一个英文逗号来分隔。 +- tag_set 格式形如 `=, =`,表示标签列数据,使用英文逗号分隔,与 field_set 之间使用一个半角空格分隔。 +- field_set 格式形如 `=, =`,表示普通列,同样使用英文逗号来分隔,与 timestamp 之间使用一个半角空格分隔。 +- timestamp 为本行数据对应的主键时间戳。 + +tag_set 中的所有的数据自动转化为 nchar 数据类型,并不需要使用双引号。 +在无模式写入数据行协议中,field_set 中的每个数据项都需要对自身的数据类型进行描述,具体要求如下。 +- 如果两边有英文双引号,表示 varchar 类型,例如 "abc"。 +- 如果两边有英文双引号而且带有 L 或 l 前缀,表示 nchar 类型,例如 L" 报错信息 "。 +- 如果两边有英文双引号而且带有 G 或 g 前缀, 表 示 geometry 类型, 例 如G"Point(4.343 89.342)"。 +- 如果两边有英文双引号而且带有 B 或 b 前缀,表示 varbinary 类型,双引号内可以为 \x 开头的十六进制或者字符串,例如 B"\x98f46e" 和 B"hello"。 +- 对于空格、等号(=)、逗号(,)、双引号(")、反斜杠(\),前面需要使用反斜杠(\)进行转义(均为英文半角符号)。无模式写入协议的域转义规则如下表所示。 + +| **序号** | **域** | **需转义字符** | +| -------- | ----------- | ----------------------------- | +| 1 | 超级表名 | 逗号,空格 | +| 2 | 标签名 | 逗号,等号,空格 | +| 3 | 标签值 | 逗号,等号,空格 | +| 4 | 列名 | 逗号,等号,空格 | +| 5 | 列值 | 双引号,反斜杠 | + +如果使用两个连续的反斜杠,则第1个反斜杠作为转义符,当只有一个反斜杠时则无须转义。无模式写入协议的反斜杠转义规则如下表所示。 + +| **序号** | **反斜杠** | **转义为** | +| -------- | ----------- | ----------------------------- | +| 1 | \ | \ | +| 2 | \\\\ | \ | +| 3 | \\\\\\ | \\\\ | +| 4 | \\\\\\\\ | \\\\ | +| 5 | \\\\\\\\\\ | \\\\\\ | +| 6 | \\\\\\\\\\\\ | \\\\\\ | + +数值类型将通过后缀来区分数据类型。无模式写入协议的数值类型转义规则如下表所示。 + +| **序号** | **后缀** | **映射类型** | **大小(字节)** | +| -------- | ----------- | ----------------------------- | -------------- | +| 1 | 无或 f64 | double | 8 | +| 2 | f32 | float | 4 | +| 3 | i8/u8 | TinyInt/UTinyInt | 1 | +| 4 | i16/u16 | SmallInt/USmallInt | 2 | +| 5 | i32/u32 | Int/UInt | 4 | +| 6 | i64/i/u64/u | BigInt/BigInt/UBigInt/UBigInt | 8 | + +- t, T, true, True, TRUE, f, F, false, False 将直接作为 BOOL 型来处理。 + +例如如下数据行表示:向名为 st 的超级表下的 t1 标签为 "3"(NCHAR)、t2 标签为 "4"(NCHAR)、t3 +标签为 "t3"(NCHAR)的数据子表,写入 c1 列为 3(BIGINT)、c2 列为 false(BOOL)、c3 +列为 "passit"(BINARY)、c4 列为 4(DOUBLE)、主键时间戳为 1626006833639000000 的一行数据。 + +```json +st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000 +``` + +需要注意的是,如果描述数据类型后缀时出现大小写错误,或者为数据指定的数据类型有误,均可能引发报错提示而导致数据写入失败。 + +TDengine提供数据写入的幂等性保证,即用户可以反复调用API进行出错数据的写入操作。无模式写入TDengine的主要处理逻辑请参考TDengine的官方网站,此处不赘述。 + +## 时间分辨率识别 + +无模式写入支持3个指定的模式,如下表所示: + +| **序号** | **值** | **说明** | +| -------- | ------------------- | ------------------------------- | +| 1 | SML_LINE_PROTOCOL | InfluxDB 行协议(Line Protocol) | +| 2 | SML_TELNET_PROTOCOL | OpenTSDB 文本行协议 | +| 3 | SML_JSON_PROTOCOL | JSON 协议格式 | + +在 SML_LINE_PROTOCOL 解析模式下,需要用户指定输入的时间戳的时间分辨率。可用的时间分辨率如下表所示: + +| **序号** | **时间分辨率定义** | **含义** | +| -------- | --------------------------------- | -------------- | +| 1 | TSDB_SML_TIMESTAMP_NOT_CONFIGURED | 未定义(无效) | +| 2 | TSDB_SML_TIMESTAMP_HOURS | 小时 | +| 3 | TSDB_SML_TIMESTAMP_MINUTES | 分钟 | +| 4 | TSDB_SML_TIMESTAMP_SECONDS | 秒 | +| 5 | TSDB_SML_TIMESTAMP_MILLI_SECONDS | 毫秒 | +| 6 | TSDB_SML_TIMESTAMP_MICRO_SECONDS | 微秒 | +| 7 | TSDB_SML_TIMESTAMP_NANO_SECONDS | 纳秒 | + +在 SML_TELNET_PROTOCOL 和 SML_JSON_PROTOCOL 模式下,根据时间戳的长度来确定时间精度(与 OpenTSDB 标准操作方式相同),此时会忽略用户指定的时间分辨率。 + +## 数据模式映射规则 + +InfluxDB行协议的数据将被映射成具有模式的数据,其中,measurement映射为超级表名称,tag_set中的标签名称映射为数据模式中的标签名,field_set中的名称映射为列名称。例如下面的数据。 + +```json +st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000 +``` + +该行数据映射生成一个超级表: st, 其包含了 3 个类型为 nchar 的标签,分别是:t1, t2, t3。五个数据列,分别是 ts(timestamp),c1 (bigint),c3(binary),c2 (bool), c4 (bigint)。映射成为如下 SQL 语句: + +```json +create stable st (_ts timestamp, c1 bigint, c2 bool, c3 binary(6), c4 bigint) tags(t1 nchar(1), t2 nchar(1), t3 nchar(2)) +``` + +## 数据模式变更处理 + +本节将说明不同行数据写入情况下,对于数据模式的影响。 + +在使用行协议写入一个明确的标识的字段类型的时候,后续更改该字段的类型定义,会出现明确的数据模式错误,即会触发写入 API 报告错误。如下所示, + +```json +st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4 1626006833639000000 +st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4i 1626006833640000000 +``` + +第一行的数据类型映射将 c4 列定义为 Double, 但是第二行的数据又通过数值后缀方式声明该列为 BigInt, 由此会触发无模式写入的解析错误。 + +如果列前面的行协议将数据列声明为了 binary, 后续的要求长度更长的 binary 长度,此时会触发超级表模式的变更。 + +```json +st,t1=3,t2=4,t3=t3 c1=3i64,c5="pass" 1626006833639000000 +st,t1=3,t2=4,t3=t3 c1=3i64,c5="passit" 1626006833640000000 +``` + +第一行中行协议解析会声明 c5 列是一个 binary(4)的字段,第二次行数据写入会提取列 c5 仍然是 binary 列,但是其宽度为 6,此时需要将 binary 的宽度增加到能够容纳 新字符串的宽度。 + +```json +st,t1=3,t2=4,t3=t3 c1=3i64 1626006833639000000 +st,t1=3,t2=4,t3=t3 c1=3i64,c6="passit" 1626006833640000000 +``` + +第二行数据相对于第一行来说增加了一个列 c6,类型为 binary(6)。那么此时会自动增加一个列 c6, 类型为 binary(6)。 + +## 无模式写入示例 + + + + +```java +public class SchemalessWsTest { + private static final String host = "127.0.0.1"; + private static final String lineDemo = "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639000000"; + private static final String telnetDemo = "stb0_0 1707095283260 4 host=host0 interface=eth0"; + private static final String jsonDemo = "{\"metric\": \"meter_current\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}"; + + public static void main(String[] args) throws SQLException { + final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata&batchfetch=true"; + try(Connection connection = DriverManager.getConnection(url)){ + init(connection); + + try(SchemalessWriter writer = new SchemalessWriter(connection, "power")){ + writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS); + writer.write(telnetDemo, SchemalessProtocolType.TELNET, SchemalessTimestampType.MILLI_SECONDS); + writer.write(jsonDemo, SchemalessProtocolType.JSON, SchemalessTimestampType.SECONDS); + } + } + } + + private static void init(Connection connection) throws SQLException { + try (Statement stmt = connection.createStatement()) { + stmt.execute("CREATE DATABASE IF NOT EXISTS power"); + stmt.execute("USE power"); + } + } +} +``` +执行带有 reqId 的无模式写入,此 reqId 可用于请求链路追踪。 + +```java +writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS, 1L); +``` + + + +## 查询写入的数据 + +运行上节的样例代码,会在 power 数据库中自动建表,我们可以通过 taos shell 或者应用程序来查询数据。下面给出用 taos shell 查询超级表和 meters 表数据的样例。 + +```shell +taos> show power.stables; + stable_name | +================================= + meter_current | + stb0_0 | + meters | +Query OK, 3 row(s) in set (0.002527s) + + + +taos> select * from power.meters limit 1 \G; +*************************** 1.row *************************** + _ts: 2021-07-11 20:33:53.639 + current: 10.300000199999999 + voltage: 219 + phase: 0.310000000000000 + groupid: 2 +location: California.SanFrancisco +Query OK, 1 row(s) in set (0.004501s) +``` \ No newline at end of file diff --git a/docs/zh/08-develop/05-stmt.md b/docs/zh/08-develop/05-stmt.md new file mode 100644 index 0000000000..f156e4675a --- /dev/null +++ b/docs/zh/08-develop/05-stmt.md @@ -0,0 +1,68 @@ +--- +title: 参数绑定写入 +sidebar_label: 参数绑定 +toc_max_heading_level: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +通过参数绑定方式写入数据时,能避免SQL语法解析的资源消耗,从而显著提升写入性能。示例代码如下。 + + + + +```java +public class WSParameterBindingBasicDemo { + + // modify host to your own + private static final String host = "127.0.0.1"; + private static final Random random = new Random(System.currentTimeMillis()); + private static final int numOfSubTable = 10, numOfRow = 10; + + public static void main(String[] args) throws SQLException { + + String jdbcUrl = "jdbc:TAOS-RS://" + host + ":6041/?batchfetch=true"; + Connection conn = DriverManager.getConnection(jdbcUrl, "root", "taosdata"); + + init(conn); + + String sql = "INSERT INTO ? USING meters TAGS(?,?) VALUES (?,?,?,?)"; + + try (TSWSPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSWSPreparedStatement.class)) { + + for (int i = 1; i <= numOfSubTable; i++) { + // set table name + pstmt.setTableName("d_bind_" + i); + + // set tags + pstmt.setTagInt(0, i); + pstmt.setTagString(1, "location_" + i); + + // set columns + long current = System.currentTimeMillis(); + for (int j = 0; j < numOfRow; j++) { + pstmt.setTimestamp(1, new Timestamp(current + j)); + pstmt.setFloat(2, random.nextFloat() * 30); + pstmt.setInt(3, random.nextInt(300)); + pstmt.setFloat(4, random.nextFloat()); + pstmt.addBatch(); + } + pstmt.executeBatch(); + } + } + + conn.close(); + } + + private static void init(Connection conn) throws SQLException { + try (Statement stmt = conn.createStatement()) { + stmt.execute("CREATE DATABASE IF NOT EXISTS power"); + stmt.execute("USE power"); + stmt.execute("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))"); + } + } +} +``` + + \ No newline at end of file diff --git a/docs/zh/08-develop/03-insert-data/60-high-volume.md b/docs/zh/08-develop/06-high.md similarity index 99% rename from docs/zh/08-develop/03-insert-data/60-high-volume.md rename to docs/zh/08-develop/06-high.md index 0a3a7a3919..8f960e20bb 100644 --- a/docs/zh/08-develop/03-insert-data/60-high-volume.md +++ b/docs/zh/08-develop/06-high.md @@ -1,3 +1,9 @@ +--- +title: 高效写入 +sidebar_label: 高效写入 +toc_max_heading_level: 4 +--- + import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; diff --git a/docs/zh/08-develop/06-stream.md b/docs/zh/08-develop/06-stream.md deleted file mode 100644 index a6c8b02772..0000000000 --- a/docs/zh/08-develop/06-stream.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -sidebar_label: 流式计算 -description: "TDengine 流式计算将数据的写入、预处理、复杂分析、实时计算、报警触发等功能融为一体,是一个能够降低用户部署成本、存储成本和运维成本的计算引擎。" -title: 流式计算 ---- - -在时序数据的处理中,经常要对原始数据进行清洗、预处理,再使用时序数据库进行长久的储存。在传统的时序数据解决方案中,常常需要部署 Kafka、Flink 等流处理系统。而流处理系统的复杂性,带来了高昂的开发与运维成本。 - -TDengine 3.0 的流式计算引擎提供了实时处理写入的数据流的能力,使用 SQL 定义实时流变换,当数据被写入流的源表后,数据会被以定义的方式自动处理,并根据定义的触发模式向目的表推送结果。它提供了替代复杂流处理系统的轻量级解决方案,并能够在高吞吐的数据写入的情况下,提供毫秒级的计算结果延迟。 - -流式计算可以包含数据过滤,标量函数计算(含UDF),以及窗口聚合(支持滑动窗口、会话窗口、状态窗口、事件窗口与计数窗口),可以以超级表、子表、普通表为源表,写入到目的超级表。在创建流时,目的超级表将被自动创建,随后新插入的数据会被流定义的方式处理并写入其中,通过 partition by 子句,可以以表名或标签划分 partition,不同的 partition 将写入到目的超级表的不同子表。 - -TDengine 的流式计算能够支持分布在多个 vnode 中的超级表聚合;还能够处理乱序数据的写入:它提供了 watermark 机制以度量容忍数据乱序的程度,并提供了 ignore expired 配置项以决定乱序数据的处理策略——丢弃或者重新计算。 - -详见 [流式计算](../../taos-sql/stream) - - -## 流式计算的创建 - -```sql -CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name AS subquery -stream_options: { - TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time] - WATERMARK time - IGNORE EXPIRED [0 | 1] -} -``` - -详细的语法规则参考 [流式计算](../../taos-sql/stream) - -## 示例一 - -企业电表的数据经常都是成百上千亿条的,那么想要将这些分散、凌乱的数据清洗或转换都需要比较长的时间,很难做到高效性和实时性,以下例子中,通过流计算可以将电表电压大于 220V 的数据清洗掉,然后以 5 秒为窗口整合并计算出每个窗口中电流的最大值,最后将结果输出到指定的数据表中。 - -### 创建 DB 和原始数据表 - -首先准备数据,完成建库、建一张超级表和多张子表操作 - -```sql -DROP DATABASE IF EXISTS power; -CREATE DATABASE power; -USE power; - -CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int); - -CREATE TABLE d1001 USING meters TAGS ("California.SanFrancisco", 2); -CREATE TABLE d1002 USING meters TAGS ("California.SanFrancisco", 3); -CREATE TABLE d1003 USING meters TAGS ("California.LosAngeles", 2); -CREATE TABLE d1004 USING meters TAGS ("California.LosAngeles", 3); -``` - -### 创建流 - -```sql -create stream current_stream trigger at_once into current_stream_output_stb as select _wstart as wstart, _wend as wend, max(current) as max_current from meters where voltage <= 220 interval (5s); -``` - -### 写入数据 -```sql -insert into d1001 values("2018-10-03 14:38:05.000", 10.30000, 219, 0.31000); -insert into d1001 values("2018-10-03 14:38:15.000", 12.60000, 218, 0.33000); -insert into d1001 values("2018-10-03 14:38:16.800", 12.30000, 221, 0.31000); -insert into d1002 values("2018-10-03 14:38:16.650", 10.30000, 218, 0.25000); -insert into d1003 values("2018-10-03 14:38:05.500", 11.80000, 221, 0.28000); -insert into d1003 values("2018-10-03 14:38:16.600", 13.40000, 223, 0.29000); -insert into d1004 values("2018-10-03 14:38:05.000", 10.80000, 223, 0.29000); -insert into d1004 values("2018-10-03 14:38:06.500", 11.50000, 221, 0.35000); -``` - -### 查询以观察结果 - -```sql -taos> select wstart, wend, max_current from current_stream_output_stb; - wstart | wend | max_current | -=========================================================================== - 2018-10-03 14:38:05.000 | 2018-10-03 14:38:10.000 | 10.30000 | - 2018-10-03 14:38:15.000 | 2018-10-03 14:38:20.000 | 12.60000 | -Query OK, 2 rows in database (0.018762s) -``` - -## 示例二 - -依然以示例一中的数据为基础,我们已经采集到了每个智能电表的电流和电压数据,现在需要求出有功功率和无功功率,并将地域和电表名以符号 "." 拼接,然后以电表名称分组输出到新的数据表中。 - -### 创建 DB 和原始数据表 - -参考示例一 [创建 DB 和原始数据表](#创建-db-和原始数据表) - -### 创建流 - -```sql -create stream power_stream trigger at_once into power_stream_output_stb as select ts, concat_ws(".", location, tbname) as meter_location, current*voltage*cos(phase) as active_power, current*voltage*sin(phase) as reactive_power from meters partition by tbname; -``` - -### 写入数据 - -参考示例一 [写入数据](#写入数据) - -### 查询以观察结果 -```sql -taos> select ts, meter_location, active_power, reactive_power from power_stream_output_stb; - ts | meter_location | active_power | reactive_power | -=================================================================================================================== - 2018-10-03 14:38:05.000 | California.LosAngeles.d1004 | 2307.834596289 | 688.687331847 | - 2018-10-03 14:38:06.500 | California.LosAngeles.d1004 | 2387.415754896 | 871.474763418 | - 2018-10-03 14:38:05.500 | California.LosAngeles.d1003 | 2506.240411679 | 720.680274962 | - 2018-10-03 14:38:16.600 | California.LosAngeles.d1003 | 2863.424274422 | 854.482390839 | - 2018-10-03 14:38:05.000 | California.SanFrancisco.d1001 | 2148.178871730 | 688.120784090 | - 2018-10-03 14:38:15.000 | California.SanFrancisco.d1001 | 2598.589176205 | 890.081451418 | - 2018-10-03 14:38:16.800 | California.SanFrancisco.d1001 | 2588.728381186 | 829.240910475 | - 2018-10-03 14:38:16.650 | California.SanFrancisco.d1002 | 2175.595991997 | 555.520860397 | -Query OK, 8 rows in database (0.014753s) -``` diff --git a/docs/zh/08-develop/07-tmq.md b/docs/zh/08-develop/07-tmq.md new file mode 100644 index 0000000000..29ac760abf --- /dev/null +++ b/docs/zh/08-develop/07-tmq.md @@ -0,0 +1,140 @@ +--- +title: 数据订阅 +sidebar_label: 数据订阅 +toc_max_heading_level: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +TDengine提供了类似Kafka的数据订阅功能。本章以 WebSocket 连接方式为例,介绍数据订阅的相关API以及使用方法。 + +## 创建主题 + +创建主题的示例代码如下。 + + + + +```java +Connection connection = DriverManager.getConnection(url, properties); +Statement statement = connection.createStatement(); +statement.executeUpdate("CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT ts, current, voltage, phase, groupid, location FROM meters"); +``` + + + +上述代码将使用SQL“select ts, current, voltage, phase, groupId, location from meters”创建一个名为topic_meters的订阅。使用该订阅所获取的消息中的每条记录都由该查询语句所选择的列组成。 + +**注意** +在TDengine中,对于订阅查询,有以下限制。 +- 查询语句限制:订阅查询只能使用 select 语句,不支持其他类型的SQL,如 insert、update或delete等。 +- 始数据查询:订阅查询只能查询原始数据,而不能查询聚合或计算结果。 +- 时间顺序限制:订阅查询只能按照时间正序查询数据。 + +## 创建消费者 + + + + +```java +Properties config = new Properties(); +config.setProperty("td.connect.type", "ws"); +config.setProperty("bootstrap.servers", "localhost:6041"); +config.setProperty("auto.offset.reset", "latest"); +config.setProperty("msg.with.table.name", "true"); +config.setProperty("enable.auto.commit", "true"); +config.setProperty("auto.commit.interval.ms", "1000"); +config.setProperty("group.id", "group1"); +config.setProperty("client.id", "1"); +config.setProperty("value.deserializer", "com.taosdata.example.AbsConsumerLoop$ResultDeserializer"); +config.setProperty("value.deserializer.encoding", "UTF-8"); + +this.consumer = new TaosConsumer<(config); +``` + + + +相关参数说明如下: +1. td.connect.type: 连接方式。jni:表示使用动态库连接的方式,ws/WebSocket:表示使用 WebSocket 进行数据通信。默认为 jni 方式。 +2. bootstrap.servers: TDengine 服务端所在的ip:port,如果使用 WebSocket 连接,则为 taosAdapter 所在的ip:port。 +3. auto.offset.reset:消费组订阅的初始位置,earliest: 从头开始订阅; latest: 仅从最新数据开始订阅。 +4. enable.auto.commit: 是否允许自动提交。 +5. group.id: consumer: 所在的 group。 +6. value.deserializer: 结果集反序列化方法,可以继承 com.taosdata.jdbc.tmq.ReferenceDeserializer,并指定结果集 bean,实现反序列化。也可以继承 com.taosdata.jdbc.tmq.Deserializer,根据 SQL 的 resultSet 自定义反序列化方式。 + +## 订阅消费数据 + +订阅消费数据的示例代码如下 + + + + +```java +while (!shutdown.get()) { + ConsumerRecords + + +poll 每次调用获取一个消息,一个消息中可能有多个记录,需要循环处理。 + +## 指定订阅的 Offset + + + + +```java +// 获取订阅的 topicPartition +Set + + +## 提交 Offset + +当 `enable.auto.commit` 为 false 时,可以手动提交 offset。 + + + + +```java +void commitSync() throws SQLException; +void commitSync(Map + + +## 取消订阅和关闭消费 + + + + +```java +// 取消订阅 +consumer.unsubscribe(); +// 关闭消费 +consumer.close() +``` + + \ No newline at end of file diff --git a/docs/zh/08-develop/07-tmq.mdx b/docs/zh/08-develop/07-tmq.mdx deleted file mode 100644 index cf0d22050f..0000000000 --- a/docs/zh/08-develop/07-tmq.mdx +++ /dev/null @@ -1,860 +0,0 @@ ---- -sidebar_label: 数据订阅 -description: "数据订阅与推送服务。写入到 TDengine 中的时序数据能够被自动推送到订阅客户端。" -title: 数据订阅 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; -import Java from "./_sub_java.mdx"; -import JavaWS from "./_sub_java_ws.mdx"; -import Python from "./_sub_python.mdx"; -import Go from "./_sub_go.mdx"; -import Rust from "./_sub_rust.mdx"; -import Node from "./_sub_node.mdx"; -import CSharp from "./_sub_cs.mdx"; -import CDemo from "./_sub_c.mdx"; - -为了帮助应用实时获取写入 TDengine 的数据,或者以事件到达顺序处理数据,TDengine 提供了类似 kafka 的数据订阅功能。这样在很多场景下,采用 TDengine 的时序数据处理系统不再需要集成消息队列产品,比如 kafka, 从而简化系统设计的复杂度,降低运营维护成本。 - -## 数据订阅介绍 - -### 主题 -与 kafka 一样,你需要定义 topic, TDengine 的 topic 有三种,可以是数据库,超级表,或者一个 `SELECT` 语句,具体的语法参见 [CREATE TOPIC](../../taos-sql/tmq)。与其他消息队列软件相比,这是 TDengine 数据订阅功能的最大的优势,它提供了更大的灵活性,数据的颗粒度可以由应用随时调整,而且数据的过滤与预处理交给 TDengine,而不是应用完成,有效的减少传输的数据量与应用的复杂度。 - -如下图,每个 topic 涉及到的数据表可能分布在多个 vnode(相当于 kafka 里的 partition) 上,每个 vnode 上的数据保存在 WAL(Write-Ahead-Log) 文件中,WAL 文件里的数据是顺序写入的(由于 WAL 文件中存储的不只有数据,还有元数据,写入消息等,所以数据的版本号不是连续的)。 - -![img_5.png](img_5.png) - -TDengine 会为 WAL 文件自动创建索引以支持快速随机访问,并提供了灵活可配置的文件切换与保留机制,用户可以按需指定 WAL 文件保留的时间以及大小(详见 [CREATE DATABASE](../../taos-sql/database) 语句,由于消费是通过 WAL 实现的,所以应该根据写入消费速度来确定 WAL 的保存时长)。通过以上方式将 WAL 改造成了一个保留事件到达顺序的、可持久化的存储引擎。 - -对于 `SELECT` 语句形式的 topic,在消费时,TDengine 根据当前消费进度从 WAL 直接读取数据,并使用统一的查询引擎实现过滤、变换等操作,将数据推送给消费者。 - -### 生产者 -写入 topic 相关联的数据表中数据的都是生产者,生产者实际生产的数据写入到了子表或普通表中,即表所在 vnode 的 WAL 里。 - -### 消费者 - -#### 消费者组 -消费者订阅 topic 后,可以消费 topic 里的所有数据(这些数据所在的表可能分布在多个 vnode 上,即 db 所在的所有 vnode)。订阅 topic 时,需要指定一个消费者组 (consumer group),如果这个消费者组里只有一个消费者,那么这个消费者会顺序的消费这些 vnode 上的数据。 - -为了提高消费速度,便于多线程、分布式地消费数据,可以在一个消费组里添加多个消费者,这些消费者将均分数据所在的 vnode 进行消费(比如数据分布在 4 个 vnode 上,有 2 个消费者的话,那么每个消费者消费 2 个 vnode;有 3 个消费者的话,2 个消费者各消费 1 个 vnode,1 个消费者消费 2 个 vnode;有 5 个消费者的话,4 个各分配 1 个 vnode 消费,另外 1 个不消费),如下图: - -![img_6.png](img_6.png) - -在一个消费组里添加一个消费者后,在 Mnode 上通过 rebalance 的机制实现消费者的重新分配,该操作对用户是透明的。 - -一个消费者可以订阅多个 topic。TDengine 的数据订阅在宕机、重启等复杂环境下确保 at least once 消费。 - -#### 消费进度 -在 topic 的一个消费组的一个 vnode 上有消费进度。消费者消费的同时,可以提交消费进度,消费进度即 vnode 上 WAL 的版本号(对于 kafka 里的 offset),消费进度可以手动提交,也可以通过参数(auto.commit.interval.ms)设置为周期性自动提交。 - -首次消费数据时通过订阅参数(auto.offset.reset)来确定消费位置为最新数据(latest)还是最旧数据(earliest)。 - -消费进度在一个 vnode 上对于同一个 topic 和 消费者组是唯一的。所以如果同一个 topic 和 消费者组在一个 vnode 上的消费者退出了,并且提交了消费进度。然后同一个 topic 和 消费者组里重新建了一个新的消费者消费这个 vnode,那么这个新消费者将继承之前的消费进度继续消费。 - -如果之前的消费者没有提交消费进度,那个新的消费者将根据订阅参数(auto.offset.reset)设置的值来确定起始消费位置。 - -不同消费者组中的消费者即使消费同一个 topic, 并不共享消费进度。 - -![img_7.png](img_7.png) - -作为一个数据库产品, WAL 文件中存储的不全是数据,也包括其他写入消息,元数据等,所以消费进度不是连续的。 - -### 说明 -从3.2.0.0版本开始,数据订阅支持vnode迁移和分裂。 - -由于数据订阅依赖wal文件,而在vnode迁移和分裂的过程中,wal并不会同步过去,所以迁移或分裂后,之前没消费完的wal数据后消费不到。所以请保证迁移和分裂之前把数据全部消费完后,再进行vnode迁移或分裂,否则,消费会丢失数据。 - -## 数据订阅语法说明 - -具体的语法参见 [数据订阅](../../taos-sql/tmq) - -## 数据订阅相关参数 - -消费参数主要用于消费者创建时指定,基础配置项如下表所示: - -| 参数名称 | 类型 | 参数说明 | 备注 | -| :----------------------------: | :-----: | -------------------------------------------------------- | ------------------------------------------- | -| `td.connect.ip` | string | 服务端的 IP 地址 | | -| `td.connect.user` | string | 用户名 | | -| `td.connect.pass` | string | 密码 | | -| `td.connect.port` | integer | 服务端的端口号 | | -| `group.id` | string | 消费组 ID,同一消费组共享消费进度 |
**必填项**。最大长度:192。
每个topic最多可建立100个 consumer group | -| `client.id` | string | 客户端 ID | 最大长度:192。 | -| `auto.offset.reset` | enum | 消费组订阅的初始位置 |
`earliest`: default(version < 3.2.0.0);从头开始订阅;
`latest`: default(version >= 3.2.0.0);仅从最新数据开始订阅;
`none`: 没有提交的 offset 无法订阅 | -| `enable.auto.commit` | boolean | 是否启用消费位点自动提交,true: 自动提交,客户端应用无需commit;false:客户端应用需要自行commit | 默认值为 true | -| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 | -| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句)(从3.2.0.0版本该参数废弃,恒为true) |默认关闭 | -| `enable.replay` | boolean | 是否开启数据回放功能 |默认关闭 | - -## 数据订阅主要 API 接口 - -不同语言下, TMQ 订阅相关的 API 及数据结构如下(详细的接口说明可以参考连接器章节数据订阅部分,注意consumer结构不是线程安全的,在一个线程使用consumer时,不要在另一个线程close这个consumer): - - - - -```c - typedef struct tmq_t tmq_t; - typedef struct tmq_conf_t tmq_conf_t; - typedef struct tmq_list_t tmq_list_t; - - typedef void(tmq_commit_cb(tmq_t *tmq, int32_t code, void *param)); - - typedef enum tmq_conf_res_t { - TMQ_CONF_UNKNOWN = -2, - TMQ_CONF_INVALID = -1, - TMQ_CONF_OK = 0, - } tmq_conf_res_t; - - typedef struct tmq_topic_assignment { - int32_t vgId; - int64_t currentOffset; - int64_t begin; - int64_t end; - } tmq_topic_assignment; - - DLL_EXPORT tmq_conf_t *tmq_conf_new(); - DLL_EXPORT tmq_conf_res_t tmq_conf_set(tmq_conf_t *conf, const char *key, const char *value); - DLL_EXPORT void tmq_conf_destroy(tmq_conf_t *conf); - DLL_EXPORT void tmq_conf_set_auto_commit_cb(tmq_conf_t *conf, tmq_commit_cb *cb, void *param); - - DLL_EXPORT tmq_list_t *tmq_list_new(); - DLL_EXPORT int32_t tmq_list_append(tmq_list_t *, const char *); - DLL_EXPORT void tmq_list_destroy(tmq_list_t *); - DLL_EXPORT int32_t tmq_list_get_size(const tmq_list_t *); - DLL_EXPORT char **tmq_list_to_c_array(const tmq_list_t *); - - DLL_EXPORT tmq_t *tmq_consumer_new(tmq_conf_t *conf, char *errstr, int32_t errstrLen); - DLL_EXPORT int32_t tmq_subscribe(tmq_t *tmq, const tmq_list_t *topic_list); - DLL_EXPORT int32_t tmq_unsubscribe(tmq_t *tmq); - DLL_EXPORT int32_t tmq_subscription(tmq_t *tmq, tmq_list_t **topics); - DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t timeout); - DLL_EXPORT int32_t tmq_consumer_close(tmq_t *tmq); - DLL_EXPORT int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg); - DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const TAOS_RES *msg, tmq_commit_cb *cb, void *param); - DLL_EXPORT int32_t tmq_commit_offset_sync(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset); - DLL_EXPORT void tmq_commit_offset_async(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset, tmq_commit_cb *cb, void *param); - DLL_EXPORT int32_t tmq_get_topic_assignment(tmq_t *tmq, const char *pTopicName, tmq_topic_assignment **assignment,int32_t *numOfAssignment); - DLL_EXPORT void tmq_free_assignment(tmq_topic_assignment* pAssignment); - DLL_EXPORT int32_t tmq_offset_seek(tmq_t *tmq, const char *pTopicName, int32_t vgId, int64_t offset); - DLL_EXPORT int64_t tmq_position(tmq_t *tmq, const char *pTopicName, int32_t vgId); - DLL_EXPORT int64_t tmq_committed(tmq_t *tmq, const char *pTopicName, int32_t vgId); - - DLL_EXPORT const char *tmq_get_topic_name(TAOS_RES *res); - DLL_EXPORT const char *tmq_get_db_name(TAOS_RES *res); - DLL_EXPORT int32_t tmq_get_vgroup_id(TAOS_RES *res); - DLL_EXPORT int64_t tmq_get_vgroup_offset(TAOS_RES* res); - DLL_EXPORT const char *tmq_err2str(int32_t code); -``` - -下面介绍一下它们的具体用法(超级表和子表结构请参考“数据建模”一节),完整的示例代码请见下面 C 语言的示例代码。 - - - - -```java -void subscribe(Collection topics) throws SQLException; - -void unsubscribe() throws SQLException; - -Set subscription() throws SQLException; - -ConsumerRecords poll(Duration timeout) throws SQLException; - -Set assignment() throws SQLException; -long position(TopicPartition partition) throws SQLException; -Map position(String topic) throws SQLException; -Map beginningOffsets(String topic) throws SQLException; -Map endOffsets(String topic) throws SQLException; -Map committed(Set partitions) throws SQLException; - -void seek(TopicPartition partition, long offset) throws SQLException; -void seekToBeginning(Collection partitions) throws SQLException; -void seekToEnd(Collection partitions) throws SQLException; - -void commitSync() throws SQLException; -void commitSync(Map offsets) throws SQLException; - -void close() throws SQLException; -``` - - - - - -```python -class Consumer: - def subscribe(self, topics): - pass - - def unsubscribe(self): - pass - - def poll(self, timeout: float = 1.0): - pass - - def assignment(self): - pass - - def seek(self, partition): - pass - - def close(self): - pass - - def commit(self, message): - pass -``` - - - - - -```go -func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error) - -// 出于兼容目的保留 rebalanceCb 参数,当前未使用 -func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error - -// 出于兼容目的保留 rebalanceCb 参数,当前未使用 -func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error - -func (c *Consumer) Poll(timeoutMs int) tmq.Event - -// 出于兼容目的保留 tmq.TopicPartition 参数,当前未使用 -func (c *Consumer) Commit() ([]tmq.TopicPartition, error) - -func (c *Consumer) Unsubscribe() error - -func (c *Consumer) Close() error -``` - - - - - -```rust -impl TBuilder for TmqBuilder - fn from_dsn(dsn: D) -> Result - fn build(&self) -> Result - -impl AsAsyncConsumer for Consumer - async fn subscribe, I: IntoIterator + Send>( - &mut self, - topics: I, - ) -> Result<(), Self::Error>; - fn stream( - &self, - ) -> Pin< - Box< - dyn '_ - + Send - + futures::Stream< - Item = Result<(Self::Offset, MessageSet), Self::Error>, - >, - >, - >; - async fn commit(&self, offset: Self::Offset) -> Result<(), Self::Error>; - - async fn unsubscribe(self); -``` - -可在 \ 上查看详细 API 说明。 - - - - - -```js -function TMQConsumer(config) - -function subscribe(topic) - -function consume(timeout) - -function subscription() - -function unsubscribe() - -function commit(msg) - -function close() -``` - - - - - -```csharp -class ConsumerBuilder - -ConsumerBuilder(IEnumerable> config) - -public IConsumer Build() - -void Subscribe(IEnumerable topics) - -void Subscribe(string topic) - -ConsumeResult Consume(int millisecondsTimeout) - -List Subscription() - -void Unsubscribe() - -List Commit() - -void Close() -``` - - - - -## 数据订阅示例 -### 写入数据 - -首先完成建库、建一张超级表和多张子表操作,然后就可以写入数据了,比如: - -```sql -DROP DATABASE IF EXISTS tmqdb; -CREATE DATABASE tmqdb WAL_RETENTION_PERIOD 3600; -CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16)); -CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0"); -CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1"); -INSERT INTO tmqdb.ctb0 VALUES(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00'); -INSERT INTO tmqdb.ctb1 VALUES(now, 1, 1, 'a1')(now+1s, 11, 11, 'a11'); -``` -### 创建 topic - -使用 SQL 创建一个 topic: - -```sql -CREATE TOPIC topic_name AS SELECT ts, c1, c2, c3 FROM tmqdb.stb WHERE c1 > 1; -``` - -### 创建消费者 consumer - -对于不同编程语言,其设置方式如下: - - - - -```c -/* 根据需要,设置消费组 (group.id)、自动提交 (enable.auto.commit)、 - 自动提交时间间隔 (auto.commit.interval.ms)、用户名 (td.connect.user)、密码 (td.connect.pass) 等参数 */ -tmq_conf_t* conf = tmq_conf_new(); -tmq_conf_set(conf, "enable.auto.commit", "true"); -tmq_conf_set(conf, "auto.commit.interval.ms", "1000"); -tmq_conf_set(conf, "group.id", "cgrpName"); -tmq_conf_set(conf, "td.connect.user", "root"); -tmq_conf_set(conf, "td.connect.pass", "taosdata"); -tmq_conf_set(conf, "auto.offset.reset", "latest"); -tmq_conf_set(conf, "msg.with.table.name", "true"); -tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL); - -tmq_t* tmq = tmq_consumer_new(conf, NULL, 0); -tmq_conf_destroy(conf); -``` - - - - -对于 Java 程序,还可以使用如下配置项: - -| 参数名称 | 类型 | 参数说明 | -| ----------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- | -| `td.connect.type` | string | 连接类型,"jni" 指原生连接,"ws" 指 websocket 连接,默认值为 "jni" | -| `bootstrap.servers` | string | 连接地址,如 `localhost:6030` | -| `value.deserializer` | string | 值解析方法,使用此方法应实现 `com.taosdata.jdbc.tmq.Deserializer` 接口或继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer` 类 | -| `value.deserializer.encoding` | string | 指定字符串解析的字符集 | | - -需要注意:此处使用 `bootstrap.servers` 替代 `td.connect.ip` 和 `td.connect.port`,以提供与 Kafka 一致的接口。 - -```java -Properties properties = new Properties(); -properties.setProperty("enable.auto.commit", "true"); -properties.setProperty("auto.commit.interval.ms", "1000"); -properties.setProperty("group.id", "cgrpName"); -properties.setProperty("bootstrap.servers", "127.0.0.1:6030"); -properties.setProperty("td.connect.user", "root"); -properties.setProperty("td.connect.pass", "taosdata"); -properties.setProperty("auto.offset.reset", "latest"); -properties.setProperty("msg.with.table.name", "true"); -properties.setProperty("value.deserializer", "com.taos.example.MetersDeserializer"); - -TaosConsumer consumer = new TaosConsumer<>(properties); - -/* value deserializer definition. */ -import com.taosdata.jdbc.tmq.ReferenceDeserializer; - -public class MetersDeserializer extends ReferenceDeserializer { -} -``` - - - - - -```go -conf := &tmq.ConfigMap{ - "group.id": "test", - "auto.offset.reset": "latest", - "td.connect.ip": "127.0.0.1", - "td.connect.user": "root", - "td.connect.pass": "taosdata", - "td.connect.port": "6030", - "client.id": "test_tmq_c", - "enable.auto.commit": "false", - "msg.with.table.name": "true", -} -consumer, err := NewConsumer(conf) -``` - - - - - -```rust -let mut dsn: Dsn = "taos://".parse()?; -dsn.set("group.id", "group1"); -dsn.set("client.id", "test"); -dsn.set("auto.offset.reset", "latest"); - -let tmq = TmqBuilder::from_dsn(dsn)?; - -let mut consumer = tmq.build()?; -``` - - - - - -Python 语言下引入 `taos` 库的 `Consumer` 类,创建一个 Consumer 示例: - -```python -from taos.tmq import Consumer - -# Syntax: `consumer = Consumer(configs)` -# -# Example: -consumer = Consumer( - { - "group.id": "local", - "client.id": "1", - "enable.auto.commit": "true", - "auto.commit.interval.ms": "1000", - "td.connect.ip": "127.0.0.1", - "td.connect.user": "root", - "td.connect.pass": "taosdata", - "auto.offset.reset": "latest", - "msg.with.table.name": "true", - } -) -``` - - - - - -```js -// 根据需要,设置消费组 (group.id)、自动提交 (enable.auto.commit)、 -// 自动提交时间间隔 (auto.commit.interval.ms)、用户名 (td.connect.user)、密码 (td.connect.pass) 等参数 - -let consumer = taos.consumer({ - 'enable.auto.commit': 'true', - 'auto.commit.interval.ms','1000', - 'group.id': 'tg2', - 'td.connect.user': 'root', - 'td.connect.pass': 'taosdata', - 'auto.offset.reset','latest', - 'msg.with.table.name': 'true', - 'td.connect.ip','127.0.0.1', - 'td.connect.port','6030' - }); -``` - - - - - -```csharp -var cfg = new Dictionary() -{ - { "group.id", "group1" }, - { "auto.offset.reset", "latest" }, - { "td.connect.ip", "127.0.0.1" }, - { "td.connect.user", "root" }, - { "td.connect.pass", "taosdata" }, - { "td.connect.port", "6030" }, - { "client.id", "tmq_example" }, - { "enable.auto.commit", "true" }, - { "msg.with.table.name", "false" }, -}; -var consumer = new ConsumerBuilder>(cfg).Build(); -``` - - - - - -上述配置中包括 consumer group ID,如果多个 consumer 指定的 consumer group ID 一样,则自动形成一个 consumer group,共享消费进度。 - -### 订阅 topics - -一个 consumer 支持同时订阅多个 topic。 - - - - -```c -// 创建订阅 topics 列表 -tmq_list_t* topicList = tmq_list_new(); -tmq_list_append(topicList, "topicName"); -// 启动订阅 -tmq_subscribe(tmq, topicList); -tmq_list_destroy(topicList); - -``` - - - - -```java -List topics = new ArrayList<>(); -topics.add("tmq_topic"); -consumer.subscribe(topics); -``` - - - - -```go -err = consumer.Subscribe("example_tmq_topic", nil) -if err != nil { - panic(err) -} -``` - - - - -```rust -consumer.subscribe(["tmq_meters"]).await?; -``` - - - - - -```python -consumer.subscribe(['topic1', 'topic2']) -``` - - - - - -```js -// 创建订阅 topics 列表 -let topics = ['topic_test'] - -// 启动订阅 -consumer.subscribe(topics); -``` - - - - - -```csharp -// 创建订阅 topics 列表 -List topics = new List(); -topics.add("tmq_topic"); -// 启动订阅 -consumer.Subscribe(topics); -``` - - - - - -### 消费 - -以下代码展示了不同语言下如何对 TMQ 消息进行消费。 - - - - -```c -// 消费数据 -while (running) { - TAOS_RES* msg = tmq_consumer_poll(tmq, timeOut); - msg_process(msg); -} -``` - -这里是一个 **while** 循环,每调用一次 tmq_consumer_poll(),获取一个消息,该消息与普通查询返回的结果集完全相同,可以使用相同的解析 API 完成消息内容的解析。 - - - - -```java -while(running){ - ConsumerRecords meters = consumer.poll(Duration.ofMillis(100)); - for (Meters meter : meters) { - processMsg(meter); - } -} -``` - - - - - -```go -for { - ev := consumer.Poll(0) - if ev != nil { - switch e := ev.(type) { - case *tmqcommon.DataMessage: - fmt.Println(e.Value()) - case tmqcommon.Error: - fmt.Fprintf(os.Stderr, "%% Error: %v: %v\n", e.Code(), e) - panic(e) - } - consumer.Commit() - } -} -``` - - - - - -```rust -{ - let mut stream = consumer.stream(); - - while let Some((offset, message)) = stream.try_next().await? { - // get information from offset - - // the topic - let topic = offset.topic(); - // the vgroup id, like partition id in kafka. - let vgroup_id = offset.vgroup_id(); - println!("* in vgroup id {vgroup_id} of topic {topic}\n"); - - if let Some(data) = message.into_data() { - while let Some(block) = data.fetch_raw_block().await? { - // one block for one table, get table name if needed - let name = block.table_name(); - let records: Vec = block.deserialize().try_collect()?; - println!( - "** table: {}, got {} records: {:#?}\n", - name.unwrap(), - records.len(), - records - ); - } - } - consumer.commit(offset).await?; - } -} -``` - - - - -```python -while True: - res = consumer.poll(100) - if not res: - continue - err = res.error() - if err is not None: - raise err - val = res.value() - - for block in val: - print(block.fetchall()) -``` - - - - - -```js -while(true){ - msg = consumer.consume(200); - // process message(consumeResult) - console.log(msg.topicPartition); - console.log(msg.block); - console.log(msg.fields) -} -``` - - - - - -```csharp -// 消费数据 -while (true) -{ - using (var result = consumer.Consume(500)) - { - if (result == null) continue; - ProcessMsg(result); - consumer.Commit(); - } -} -``` - - - - - -### 结束消费 - -消费结束后,应当取消订阅。 - - - - -```c -/* 取消订阅 */ -tmq_unsubscribe(tmq); - -/* 关闭消费者对象 */ -tmq_consumer_close(tmq); -``` - - - - -```java -/* 取消订阅 */ -consumer.unsubscribe(); - -/* 关闭消费 */ -consumer.close(); -``` - - - - - -```go -/* Unsubscribe */ -_ = consumer.Unsubscribe() - -/* Close consumer */ -_ = consumer.Close() -``` - - - - - -```rust -consumer.unsubscribe().await; -``` - - - - - -```py -# 取消订阅 -consumer.unsubscribe() -# 关闭消费 -consumer.close() -``` - - - - -```js -consumer.unsubscribe(); -consumer.close(); -``` - - - - - -```csharp -// 取消订阅 -consumer.Unsubscribe(); - -// 关闭消费 -consumer.Close(); -``` - - - - - -### 完整示例代码 - -以下是各语言的完整示例代码。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## 数据订阅高级功能 -### 数据回放 -- 订阅支持 replay 功能,按照数据写入的时间回放。 - 比如,如下时间写入三条数据 - ```sql - 2023/09/22 00:00:00.000 - 2023/09/22 00:00:05.000 - 2023/09/22 00:00:08.000 - ``` - 则订阅出第一条数据 5s 后返回第二条数据,获取第二条数据 3s 后返回第三条数据。 -- 仅查询订阅支持数据回放 - - 回放需要保证独立时间线 - - 如果是子表订阅或者普通表订阅,只有一个vnode上有数据,保证是一个时间线 - - 如果超级表订阅,则需保证该 DB 只有一个vnode,否则报错(因为多个vnode上订阅出的数据不在一个时间线上) -- 超级表和库订阅不支持回放 -- enable.replay 参数,true表示开启订阅回放功能,false表示不开启订阅回放功能,默认不开启。 -- 回放不支持进度保存,所以回放参数 enable.replay = true 时,auto commit 自动关闭 -- 因为数据回放本身需要处理时间,所以回放的精度存在几十ms的误差 diff --git a/docs/zh/08-develop/08-cache.md b/docs/zh/08-develop/08-cache.md deleted file mode 100644 index 07479b9a27..0000000000 --- a/docs/zh/08-develop/08-cache.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -sidebar_label: 缓存 -title: 缓存 -description: "TDengine 内部的缓存设计" ---- - -为了实现高效的写入和查询,TDengine 充分利用了各种缓存技术,本节将对 TDengine 中对缓存的使用做详细的说明。 - -## 写缓存 - -TDengine 采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Used,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine 充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。 - -每个 vnode 的写入缓存大小在创建数据库时决定,创建数据库时的两个关键参数 vgroups 和 buffer 分别决定了该数据库中的数据由多少个 vgroup 处理,以及向其中的每个 vnode 分配多少写入缓存。buffer 的单位是MB。 - -```sql -create database db0 vgroups 100 buffer 16 -``` - -理论上缓存越大越好,但超过一定阈值后再增加缓存对写入性能提升并无帮助,一般情况下使用默认值即可。 - -## 读缓存 - -在创建数据库时可以选择是否缓存该数据库中每个子表的最新数据。由参数 cachemodel 设置,分为四种情况: -- none: 不缓存 -- last_row: 缓存子表最近一行数据,这将显著改善 last_row 函数的性能 -- last_value: 缓存子表每一列最近的非 NULL 值,这将显著改善无特殊影响(比如 WHERE, ORDER BY, GROUP BY, INTERVAL)时的 last 函数的性能 -- both: 同时缓存最近的行和列,即等同于上述 cachemodel 值为 last_row 和 last_value 的行为同时生效 - -## 元数据缓存 - -为了更高效地处理查询和写入,每个 vnode 都会缓存自己曾经获取到的元数据。元数据缓存由创建数据库时的两个参数 pages 和 pagesize 决定。pagesize 的单位是 kb。 - -```sql -create database db0 pages 128 pagesize 16 -``` - -上述语句会为数据库 db0 的每个 vnode 创建 128 个 page,每个 page 16kb 的元数据缓存。 - -## 文件系统缓存 - -TDengine 利用 WAL 技术来提供基本的数据可靠性。写入 WAL 本质上是以顺序追加的方式写入磁盘文件。此时文件系统缓存在写入性能中也会扮演关键角色。在创建数据库时可以利用 wal 参数来选择性能优先或者可靠性优先。 -- 1: 写 WAL 但不执行 fsync ,新写入 WAL 的数据保存在文件系统缓存中但并未写入磁盘,这种方式性能优先 -- 2: 写 WAL 且执行 fsync,新写入 WAL 的数据被立即同步到磁盘上,可靠性更高 - -## 客户端缓存 - -为了进一步提升整个系统的处理效率,除了以上提到的服务端缓存技术之外,在 TDengine 的所有客户端都要调用的核心库 libtaos.so (也称为 taosc )中也充分利用了缓存技术。在 taosc 中会缓存所访问过的各个数据库、超级表以及子表的元数据,集群的拓扑结构等关键元数据。 - -当有多个客户端同时访问 TDengine 集群,且其中一个客户端对某些元数据进行了修改的情况下,有可能会出现其它客户端所缓存的元数据不同步或失效的情况,此时需要在客户端执行 "reset query cache" 以让整个缓存失效从而强制重新拉取最新的元数据重新建立缓存。 diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md index aa2e3b3100..45e4ae6134 100644 --- a/docs/zh/08-develop/09-udf.md +++ b/docs/zh/08-develop/09-udf.md @@ -1,16 +1,16 @@ --- -sidebar_label: 用户定义函数 -title: UDF(用户定义函数) -description: "支持用户编码的聚合函数和标量函数,在查询中嵌入并使用用户定义函数,拓展查询的能力和功能。" +sidebar_label: UDF +title: 用户自定义函数 +toc_max_heading_level: 4 --- -在有些应用场景中,应用逻辑需要的查询无法直接使用系统内置的函数来表示。利用 UDF(User Defined Function) 功能,TDengine 可以插入用户编写的处理代码并在查询中使用它们,就能够很方便地解决特殊应用场景中的使用需求。 UDF 通常以数据表中的一列数据做为输入,同时支持以嵌套子查询的结果作为输入。 +## UDF 简介 -用户可以通过 UDF 实现两类函数:标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值 abs,正弦函数 sin,字符串拼接函数 concat 等。聚合函数对多行数据进行输出一个值,如求平均数 avg,最大值 max 等。 +在某些应用场景中,应用逻辑需要的查询功能无法直接使用TDengine内置的函数来实现。TDengine允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF在集群中注册成功后,可以像系统内置函数一样在SQL中调用,就使用角度而言没有任何区别。UDF分为标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值abs、正弦函数sin、字符串拼接函数concat等。聚合函数对多行数据输出一个值,如求平均数avg、取最大值max等。 -TDengine 支持通过 C/Python 语言进行 UDF 定义。接下来结合示例讲解 UDF 的使用方法。 +TDengine支持用C和Python两种编程语言编写UDF。C语言编写的UDF与内置函数的性能几乎相同,Python语言编写的UDF可以利用丰富的Python运算库。为了避免UDF执行中发生异常影响数据库服务,TDengine使用了进程分离技术,把UDF的执行放到另一个进程中完成,即使用户编写的UDF崩溃,也不会影响TDengine的正常运行。 -## 用 C 语言实现 UDF +## 用 C 语言开发 UDF 使用 C 语言实现 UDF 时,需要实现规定的接口函数 - 标量函数需要实现标量接口函数 scalarfn 。 @@ -19,331 +19,171 @@ TDengine 支持通过 C/Python 语言进行 UDF 定义。接下来结合示例 接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(`_start`, `_finish`, `_init`, `_destroy`)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。 -### 用 C 语言实现标量函数 -标量函数实现模板如下 -```c -#include "taos.h" -#include "taoserror.h" -#include "taosudf.h" +### 接口定义 -// initialization function. if no initialization, we can skip definition of it. The initialization function shall be concatenation of the udf name and _init suffix -// @return error number defined in taoserror.h -int32_t scalarfn_init() { - // initialization. - return TSDB_CODE_SUCCESS; -} - -// scalar function main computation function -// @param inputDataBlock, input data block composed of multiple columns with each column defined by SUdfColumn -// @param resultColumn, output column -// @return error number defined in taoserror.h -int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn* resultColumn) { - // read data from inputDataBlock and process, then output to resultColumn. - return TSDB_CODE_SUCCESS; -} - -// cleanup function. if no cleanup related processing, we can skip definition of it. The destroy function shall be concatenation of the udf name and _destroy suffix. -// @return error number defined in taoserror.h -int32_t scalarfn_destroy() { - // clean up - return TSDB_CODE_SUCCESS; -} -``` -scalarfn 为函数名的占位符,需要替换成函数名,如bit_and。 - -### 用 C 语言实现聚合函数 - -聚合函数的实现模板如下 -```c -#include "taos.h" -#include "taoserror.h" -#include "taosudf.h" - -// Initialization function. if no initialization, we can skip definition of it. The initialization function shall be concatenation of the udf name and _init suffix -// @return error number defined in taoserror.h -int32_t aggfn_init() { - // initialization. - return TSDB_CODE_SUCCESS; -} - -// aggregate start function. The intermediate value or the state(@interBuf) is initialized in this function. The function name shall be concatenation of udf name and _start suffix -// @param interbuf intermediate value to initialize -// @return error number defined in taoserror.h -int32_t aggfn_start(SUdfInterBuf* interBuf) { - // initialize intermediate value in interBuf - return TSDB_CODE_SUCCESS; -} - -// aggregate reduce function. This function aggregate old state(@interbuf) and one data bock(inputBlock) and output a new state(@newInterBuf). -// @param inputBlock input data block -// @param interBuf old state -// @param newInterBuf new state -// @return error number defined in taoserror.h -int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) { - // read from inputBlock and interBuf and output to newInterBuf - return TSDB_CODE_SUCCESS; -} - -// aggregate function finish function. This function transforms the intermediate value(@interBuf) into the final output(@result). The function name must be concatenation of aggfn and _finish suffix. -// @interBuf : intermediate value -// @result: final result -// @return error number defined in taoserror.h -int32_t int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) { - // read data from inputDataBlock and process, then output to result - return TSDB_CODE_SUCCESS; -} - -// cleanup function. if no cleanup related processing, we can skip definition of it. The destroy function shall be concatenation of the udf name and _destroy suffix. -// @return error number defined in taoserror.h -int32_t aggfn_destroy() { - // clean up - return TSDB_CODE_SUCCESS; -} -``` -aggfn为函数名的占位符,需要修改为自己的函数名,如l2norm。 - -### C 语言 UDF 接口函数定义 - -接口函数的名称是 udf 名称,或者是 udf 名称和特定后缀(_start, _finish, _init, _destroy)的连接。以下描述中函数名称中的 scalarfn,aggfn, udf 需要替换成udf函数名。 - -接口函数返回值表示是否成功。如果返回值是 TSDB_CODE_SUCCESS,表示操作成功,否则返回的是错误代码。错误代码定义在 taoserror.h,和 taos.h 中的API共享错误码的定义。例如, TSDB_CODE_UDF_INVALID_INPUT 表示输入无效输入。TSDB_CODE_OUT_OF_MEMORY 表示内存不足。 - -接口函数参数类型见数据结构定义。 +在TDengine中,UDF的接口函数名称可以是UDF名称,也可以是UDF名称和特定后缀(如_start、_finish、_init、_destroy)的连接。后面内容中描述的函数名称,例如scalarfn、aggfn,需要替换成UDF名称。。 #### 标量函数接口 - `int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)` - - 其中 scalarFn 是函数名的占位符。这个函数对数据块进行标量计算,通过设置resultColumn结构体中的变量设置值 +标量函数是一种将输入数据转换为输出数据的函数,通常用于对单个数据值进行计算和转换。标量函数的接口函数原型如下。 -参数的具体含义是: - - inputDataBlock: 输入的数据块 - - resultColumn: 输出列 +```c +int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn) +``` +主要参数说明如下。 +- inputDataBlock:输入的数据块。 +- resultColumn:输出列。 #### 聚合函数接口 -`int32_t aggfn_start(SUdfInterBuf *interBuf)` +聚合函数是一种特殊的函数,用于对数据进行分组和计算,从而生成汇总信息。聚合函数的工作原理如下。 +- 初始化结果缓冲区:首先调用aggfn_start函数,生成一个结果缓冲区(result buffer),用于存储中间结果。 +- 分组数据:相关数据会被分为多个行数据块(row data block),每个行数据块包含一组具有相同分组键(grouping key)的数据。 +- 更新中间结果:对于每个数据块,调用aggfn函数更新中间结果。aggfn函数会根据聚合函数的类型(如sum、avg、count等)对数据进行相应的计算,并将计算结 +果存储在结果缓冲区中。 +- 生成最终结果:在所有数据块的中间结果更新完成后,调用aggfn_finish函数从结果缓冲区中提取最终结果。最终结果通常只包含0条或1条数据,具体取决于聚 +合函数的类型和输入数据。 -`int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf)` +聚合函数的接口函数原型如下。 + +```c +int32_t aggfn_start(SUdfInterBuf *interBuf) +int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) +int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) +``` -`int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)` 其中 aggfn 是函数名的占位符。首先调用aggfn_start生成结果buffer,然后相关的数据会被分为多个行数据块,对每个数据块调用 aggfn 用数据块更新中间结果,最后再调用 aggfn_finish 从中间结果产生最终结果,最终结果只能含 0 或 1 条结果数据。 -参数的具体含义是: - - interBuf:中间结果 buffer。 - - inputBlock:输入的数据块。 - - newInterBuf:新的中间结果buffer。 - - result:最终结果。 +主要参数说明如下。 +- interBuf:中间结果缓存区。 +- inputBlock:输入的数据块。 +- newInterBuf:新的中间结果缓冲区。 +- result:最终结果。 #### 初始化和销毁接口 -`int32_t udf_init()` -`int32_t udf_destroy()` - -其中 udf 是函数名的占位符。udf_init 完成初始化工作。 udf_destroy 完成清理工作。如果没有初始化工作,无需定义udf_init函数。如果没有清理工作,无需定义udf_destroy函数。 - - -### C 语言 UDF 数据结构 -```c -typedef struct SUdfColumnMeta { - int16_t type; - int32_t bytes; - uint8_t precision; - uint8_t scale; -} SUdfColumnMeta; - -typedef struct SUdfColumnData { - int32_t numOfRows; - int32_t rowsAlloc; - union { - struct { - int32_t nullBitmapLen; - char *nullBitmap; - int32_t dataLen; - char *data; - } fixLenCol; - - struct { - int32_t varOffsetsLen; - int32_t *varOffsets; - int32_t payloadLen; - char *payload; - int32_t payloadAllocLen; - } varLenCol; - }; -} SUdfColumnData; - -typedef struct SUdfColumn { - SUdfColumnMeta colMeta; - bool hasNull; - SUdfColumnData colData; -} SUdfColumn; - -typedef struct SUdfDataBlock { - int32_t numOfRows; - int32_t numOfCols; - SUdfColumn **udfCols; -} SUdfDataBlock; - -typedef struct SUdfInterBuf { - int32_t bufLen; - char* buf; - int8_t numOfResult; //zero or one -} SUdfInterBuf; -``` -数据结构说明如下: - -- SUdfDataBlock 数据块包含行数 numOfRows 和列数 numCols。udfCols[i] (0 \<= i \<= numCols-1)表示每一列数据,类型为SUdfColumn*。 -- SUdfColumn 包含列的数据类型定义 colMeta 和列的数据 colData。 -- SUdfColumnMeta 成员定义同 taos.h 数据类型定义。 -- SUdfColumnData 数据可以变长,varLenCol 定义变长数据,fixLenCol 定义定长数据。 -- SUdfInterBuf 定义中间结构 buffer,以及 buffer 中结果个数 numOfResult - -为了更好的操作以上数据结构,提供了一些便利函数,定义在 taosudf.h。 - -### 编译 C UDF - -用户定义函数的 C 语言源代码无法直接被 TDengine 系统使用,而是需要先编译为 动态链接库,之后才能载入 TDengine 系统。 - -例如,按照上一章节描述的规则准备好了用户定义函数的源代码 bit_and.c,以 Linux 为例可以执行如下指令编译得到动态链接库文件: - -```bash -gcc -g -O0 -fPIC -shared bit_and.c -o libbitand.so -``` - -这样就准备好了动态链接库 libbitand.so 文件,可以供后文创建 UDF 时使用了。为了保证可靠的系统运行,编译器 GCC 推荐使用 7.5 及以上版本。 - -### C UDF 示例代码 - -#### 标量函数示例 [bit_and](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/bit_and.c) - -bit_add 实现多列的按位与功能。如果只有一列,返回这一列。bit_add 忽略空值。 - -
-bit_and.c +初始化和销毁接口是标量函数和聚合函数共同使用的接口,相关API如下。 ```c -{{#include tests/script/sh/bit_and.c}} +int32_t udf_init() +int32_t udf_destroy() ``` -
+其中,udf_init函数完成初始化工作,udf_destroy函数完成清理工作。如果没有初始化工作,无须定义udf_init函数;如果没有清理工作,无须定义udf_destroy函数。 -#### 聚合函数示例1 返回值为数值类型 [l2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/l2norm.c) - -l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。 - -
-l2norm.c +### 标量函数模板 +用C语言开发标量函数的模板如下。 ```c -{{#include tests/script/sh/l2norm.c}} +int32_t scalarfn_init() { + return TSDB_CODE_SUCCESS; +} +int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn* resultColumn) { + return TSDB_CODE_SUCCESS; +} +int32_t scalarfn_destroy() { + return TSDB_CODE_SUCCESS; +} ``` +### 聚合函数模板 -
- -#### 聚合函数示例2 返回值为字符串类型 [max_vol](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/max_vol.c) - -max_vol 实现了从多个输入的电压列中找到最大电压,返回由设备ID + 最大电压所在(行,列)+ 最大电压值 组成的组合字符串值 - -创建表: -```bash -create table battery(ts timestamp, vol1 float, vol2 float, vol3 float, deviceId varchar(16)); -``` -创建自定义函数: -```bash -create aggregate function max_vol as '/root/udf/libmaxvol.so' outputtype binary(64) bufsize 10240 language 'C'; -``` -使用自定义函数: -```bash -select max_vol(vol1,vol2,vol3,deviceid) from battery; -``` - -
-max_vol.c - +用C语言开发聚合函数的模板如下。 ```c -{{#include tests/script/sh/max_vol.c}} +int32_t aggfn_init() { + return TSDB_CODE_SUCCESS; +} +int32_t aggfn_start(SUdfInterBuf* interBuf) { + return TSDB_CODE_SUCCESS; +} +int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) { + return TSDB_CODE_SUCCESS; +} +int32_t int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) { + return TSDB_CODE_SUCCESS; +} +int32_t aggfn_destroy() { + return TSDB_CODE_SUCCESS; +} ``` -
+### 编译 -## 用 Python 语言实现 UDF +在TDengine中,为了实现UDF,需要编写C语言源代码,并按照TDengine的规范编译为动态链接库文件。 +按照前面描述的规则,准备UDF的源代码bit_and.c。以Linux操作系统为例,执行如下指令,编译得到动态链接库文件。 +```shell +gcc-g-O0-fPIC-sharedbit_and.c-olibbitand.so +``` + +为了保证可靠运行,推荐使用7.5及以上版本的GCC。 + +## 用 Python 语言开发 UDF ### 准备环境 -1. 准备好 Python 运行环境 - -2. 安装 Python 包 `taospyudf` - -```shell -pip3 install taospyudf -``` - -安装过程中会编译 C++ 源码,因此系统上要有 cmake 和 gcc。编译生成的 libtaospyudf.so 文件自动会被复制到 /usr/local/lib/ 目录,因此如果是非 root 用户,安装时需加 sudo。安装完可以检查这个目录是否有了这个文件: - -```shell -root@slave11 ~/udf $ ls -l /usr/local/lib/libtaos* --rw-r--r-- 1 root root 671344 May 24 22:54 /usr/local/lib/libtaospyudf.so -``` - -然后执行命令 -```shell -ldconfig -``` - -3. 如果 Python UDF 程序执行时,通过 PYTHONPATH 引用其它的包,可以设置 taos.cfg 的 UdfdLdLibPath 变量为PYTHONPATH的内容 - -4. 启动 `taosd` 服务 -细节请参考 [立即开始](../../get-started) +准备环境的具体步骤如下: +- 第1步,准备好Python运行环境。 +- 第2步,安装Python包taospyudf。命令如下。 + ```shell + pip3 install taospyudf + ``` +- 第3步,执行命令ldconfig。 +- 第4步,启动taosd服务。 ### 接口定义 -#### 接口概述 - -使用 Python 语言实现 UDF 时,需要实现规定的接口函数 -- 标量函数需要实现标量接口函数 process 。 -- 聚合函数需要实现聚合接口函数 start ,reduce ,finish。 -- 如果需要初始化,实现 init;如果需要清理工作,实现 destroy。 +当使用Python语言开发UDF时,需要实现规定的接口函数。具体要求如下。 +- 标量函数需要实现标量接口函数process。 +- 聚合函数需要实现聚合接口函数start、reduce、finish。 +- 如果需要初始化,则应实现函数init。 +- 如果需要清理工作,则实现函数destroy。 #### 标量函数接口 + +标量函数的接口如下。 ```Python def process(input: datablock) -> tuple[output_type]: ``` -说明: - - input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象 - - 返回值是一个 Python 对象元组,每个元素类型为输出类型。 +主要参数说明如下: +- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象 +- 返回值是一个 Python 对象元组,每个元素类型为输出类型。 #### 聚合函数接口 + +聚合函数的接口如下。 ```Python def start() -> bytes: def reduce(inputs: datablock, buf: bytes) -> bytes def finish(buf: bytes) -> output_type: ``` -说明: - - 首先调用 start 生成最初结果 buffer - - 然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果 - - 最后再调用 finish 从中间结果 buf 产生最终输出,最终输出只能含 0 或 1 条数据。 +上述代码定义了3个函数,分别用于实现一个自定义的聚合函数。具体过程如下。 + +首先,调用start函数生成最初的结果缓冲区。这个结果缓冲区用于存储聚合函数的内部状态,随着输入数据的处理而不断更新。 + +然后,输入数据会被分为多个行数据块。对于每个行数据块,调用reduce函数,并将当前行数据块(inputs)和当前的中间结果(buf)作为参数传递。reduce函数会根据输入数据和当前状态来更新聚合函数的内部状态,并返回新的中间结果 + +最后,当所有行数据块都处理完毕后,调用finish函数。这个函数接收最终的中间结果(buf)作为参数,并从中生成最终的输出。由于聚合函数的特性,最终输出只能包含0条或1条数据。这个输出结果将作为聚合函数的计算结果返回给调用者。 #### 初始化和销毁接口 + +初始化和销毁的接口如下。 ```Python def init() def destroy() ``` -说明: - - init 完成初始化工作 - - destroy 完成清理工作 +参数说明: +- init 完成初始化工作 +- destroy 完成清理工作 -### Python UDF 函数模板 +**注意** 用Python开发UDF时必须定义init函数和destroy函数 -#### 标量函数实现模板 - -标量函数实现模版如下 +### 标量函数模板 +用Python语言开发标量函数的模板如下。 ```Python def init(): # initialization @@ -351,12 +191,9 @@ def destroy(): # destroy def process(input: datablock) -> tuple[output_type]: ``` +### 聚合函数模板 -注意:定义标题函数最重要是要实现 process 函数,同时必须定义 init 和 destroy 函数即使什么都不做 - -#### 聚合函数实现模板 - -聚合函数实现模版如下 +用Python语言开发聚合函数的模板如下。 ```Python def init(): #initialization @@ -374,11 +211,9 @@ def finish(buf: bytes) -> output_type: #return obj of type outputtype ``` -注意:定义聚合函数最重要是要实现 start, reduce 和 finish,且必须定义 init 和 destroy 函数。start 生成最初结果 buffer,然后输入数据会被分为多个行数据块,对每个数据块 inputs 和当前中间结果 buf 调用 reduce,得到新的中间结果,最后再调用 finish 从中间结果 buf 产生最终输出。 - ### 数据类型映射 -下表描述了TDengine SQL数据类型和Python数据类型的映射。任何类型的NULL值都映射成Python的None值。 +下表描述了TDengine SQL 数据类型和 Python 数据类型的映射。任何类型的 NULL 值都映射成 Python 的 None 值。 | **TDengine SQL数据类型** | **Python数据类型** | | :-----------------------: | ------------ | @@ -390,19 +225,13 @@ def finish(buf: bytes) -> output_type: |TIMESTAMP | int | |JSON and other types | 不支持 | -### 开发指南 +### 开发示例 -本文内容由浅入深包括 4 个示例程序: -1. 定义一个只接收一个整数的标量函数: 输入 n, 输出 ln(n^2 + 1)。 -2. 定义一个接收 n 个整数的标量函数, 输入 (x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: x1 + 2 * x2 + ... + n * xn。 -3. 定义一个标量函数,输入一个时间戳,输出距离这个时间最近的下一个周日。完成这个函数要用到第三方库 moment。我们在这个示例中讲解使用第三方库的注意事项。 -4. 定义一个聚合函数,计算某一列最大值和最小值的差, 也就是实现 TDengine 内置的 spread 函数。 -同时也包含大量实用的 debug 技巧。 -本文假设你用的是 Linux 系统,且已安装好了 TDengine 3.0.4.0+ 和 Python 3.7+。 +本文内容由浅入深包括 5 个示例程序,同时也包含大量实用的 debug 技巧。 注意:**UDF 内无法通过 print 函数输出日志,需要自己写文件或用 python 内置的 logging 库写文件**。 -#### 最简单的 UDF +#### 示例一 编写一个只接收一个整数的 UDF 函数: 输入 n, 输出 ln(n^2 + 1)。 首先编写一个 Python 文件,存在系统某个目录,比如 /root/udf/myfun.py 内容如下 @@ -494,7 +323,7 @@ taos> select myfun(v1) from t; 至此,我们完成了第一个 UDF 😊,并学会了简单的 debug 方法。 -#### 示例二:异常处理 +#### 示例二 上面的 myfun 虽然测试测试通过了,但是有两个缺点: @@ -547,7 +376,7 @@ At: 至此,我们学会了如何更新 UDF,并查看 UDF 输出的错误日志。 (注:如果 UDF 更新后未生效,在 TDengine 3.0.5.0 以前(不含)的版本中需要重启 taosd,在 3.0.5.0 及之后的版本中不需要重启 taosd 即可生效。) -#### 示例三: 接收 n 个参数的 UDF +#### 示例三 编写一个 UDF:输入(x1, x2, ..., xn), 输出每个值和它们的序号的乘积的和: 1 * x1 + 2 * x2 + ... + n * xn。如果 x1 至 xn 中包含 null,则结果为 null。 这个示例与示例一的区别是,可以接受任意多列作为输入,且要处理每一列的值。编写 UDF 文件 /root/udf/nsum.py: @@ -598,7 +427,7 @@ taos> select ts, v1, v2, v3, nsum(v1, v2, v3) from t; Query OK, 4 row(s) in set (0.010653s) ``` -#### 示例四:使用第三方库 +#### 示例四 编写一个 UDF,输入一个时间戳,输出距离这个时间最近的下一个周日。比如今天是 2023-05-25, 则下一个周日是 2023-05-28。 完成这个函数要用到第三方库 momen。先安装这个库: @@ -690,7 +519,7 @@ taos> select ts, nextsunday(ts) from t; Query OK, 4 row(s) in set (1.011474s) ``` -#### 示例五:聚合函数 +#### 示例五 编写一个聚合函数,计算某一列最大值和最小值的差。 聚合函数与标量函数的区别是:标量函数是多行输入对应多个输出,聚合函数是多行输入对应一个输出。聚合函数的执行过程有点像经典的 map-reduce 框架的执行过程,框架把数据分成若干块,每个 mapper 处理一个块,reducer 再把 mapper 的结果做聚合。不一样的地方在于,对于 TDengine Python UDF 中的 reduce 函数既有 map 的功能又有 reduce 的功能。reduce 函数接受两个参数:一个是自己要处理的数据,一个是别的任务执行 reduce 函数的处理结果。如下面的示例 /root/udf/myspread.py: @@ -798,90 +627,54 @@ close log file: spread.log 通过这个示例,我们学会了如何定义聚合函数,并打印自定义的日志信息。 -### SQL 命令 +## 管理 UDF -1. 创建标量函数的语法 +在集群中管理UDF的过程涉及创建、使用和维护这些函数。用户可以通过SQL在集群中创建和管理UDF,一旦创建成功,集群的所有用户都可以在SQL中使用这些函数。由于UDF存储在集群的mnode上,因此即使重启集群,已经创建的UDF也仍然可用。 +在创建UDF时,需要区分标量函数和聚合函数。标量函数接受零个或多个输入参数,并返回一个单一的值。聚合函数接受一组输入值,并通过对这些值进行某种计算(如求和、计数等)来返回一个单一的值。如果创建时声明了错误的函数类别,则通过SQL调用函数时会报错。 + +此外,用户需要确保输入数据类型与UDF程序匹配,UDF输出的数据类型与outputtype匹配。这意味着在创建UDF时,需要为输入参数和输出值指定正确的数据类型。这有助于确保在调用UDF时,输入数据能够正确地传递给UDF,并且UDF的输出值与预期的数据类型相匹配。 + +### 创建标量函数 + +创建标量函数的SQL语法如下。 ```sql CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python'; ``` +各参数说明如下。 +- or replace:如果函数已经存在,则会修改已有的函数属性。 +- function_name:标量函数在SQL中被调用时的函数名。 +- language:支持C语言和Python语言(3.7及以上版本),默认为C。 +- library_path:如果编程语言是C,则路径是包含UDF实现的动态链接库的库文件绝对路径,通常指向一个so文件。如果编程语言是Python,则路径是包含UDF +实现的Python文件路径。路径需要用英文单引号或英文双引号括起来。 +- output_type:函数计算结果的数据类型名称。 -2. 创建聚合函数的语法 +### 创建聚合函数 + +创建聚合函数的SQL语法如下。 ```sql CREATE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python'; ``` -3. 更新标量函数 +其中,buffer_size 表示中间计算结果的缓冲区大小,单位是字节。其他参数的含义与标量函数相同。 +如下SQL创建一个名为 l2norm 的UDF。 ```sql -CREATE OR REPLACE FUNCTION function_name AS OUTPUTTYPE int LANGUAGE 'Python'; +CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8; ``` -4. 更新聚合函数 - +### 删除 UDF + +删除指定名称的 UDF 的 SQL 语法如下: ```sql -CREATE OR REPLACE AGGREGATE FUNCTION function_name AS OUTPUTTYPE BUFSIZE buf_size int LANGUAGE 'Python'; -``` - -注意:如果加了 “AGGREGATE” 关键字,更新之后函数将被当作聚合函数,无论之前是什么类型的函数。相反,如果没有加 “AGGREGATE” 关键字,更新之后的函数将被当作标量函数,无论之前是什么类型的函数。 - -5. 查看函数信息 - - 同名的 UDF 每更新一次,版本号会增加 1。 - -```sql -select * from ins_functions \G; -``` - -6. 查看和删除已有的 UDF - -```sql -SHOW functions; DROP FUNCTION function_name; ``` +### 查看 UDF -上面的命令可以查看 UDF 的完整信息 - -### 更多 Python UDF 示例代码 -#### 标量函数示例 [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py) - -pybitand 实现多列的按位与功能。如果只有一列,返回这一列。pybitand 忽略空值。 - -
-pybitand.py - -```Python -{{#include tests/script/sh/pybitand.py}} +显示集群中当前可用的所有UDF的SQL如下。 +```sql +show functions; ``` -
- -#### 聚合函数示例 [pyl2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pyl2norm.py) - -pyl2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。 - -
-pyl2norm.py - -```c -{{#include tests/script/sh/pyl2norm.py}} -``` - -
- -#### 聚合函数示例 [pycumsum](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pycumsum.py) - -pycumsum 使用 numpy 计算输入列所有数据的累积和。 -
-pycumsum.py - -```c -{{#include tests/script/sh/pycumsum.py}} -``` - -
-## 管理和使用 UDF -在使用 UDF 之前需要先将其加入到 TDengine 系统中。关于如何管理和使用 UDF,请参考[管理和使用 UDF](../../taos-sql/udf) - diff --git a/docs/zh/08-develop/12-third-party.md b/docs/zh/08-develop/12-third-party.md new file mode 100644 index 0000000000..0b8ce3ebc5 --- /dev/null +++ b/docs/zh/08-develop/12-third-party.md @@ -0,0 +1,228 @@ +--- +title: 与第三方集成 +sidebar_label: 与第三方集成 +toc_max_heading_level: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +TDengine是一个高性能、可扩展的时序数据库,它支持SQL查询语言,兼容标准的JDBC和ODBC接口,同时还支持RESTful接口。这使得TDengine能够轻松地与各种商业智能软件和工具集成,从而构建一个开放的技术生态系统。本章将简要介绍TDengine 如何与一些流行的第三方工具进行集成。 + +## Grafana + +Grafana是一个广受欢迎的开源可视化和分析工具,旨在帮助用户轻松地查询、可视化和监控存储在不同位置的指标、日志和跟踪信息。通过Grafana,用户可以将时序数据库中的数据以直观的图表形式展示出来,实现数据的可视化分析。 + +为了方便用户在Grafana中集成TDengine并展示时序数据,TDengine团队提供了一个名为TDengine Datasource的Grafana插件。通过安装此插件,用户无须编写任何代码,即可实现TDengine与Grafana的快速集成。这使得用户能够轻松地将存储在TDengine 中的时序数据以可视化的方式呈现在Grafana的仪表盘中,从而更好地监控和分析数据库性能。 + +### 前置条件 + +要让 Grafana 能正常添加 TDengine 数据源,需要以下几方面的准备工作。 +1. TDengine 集群已经部署并正常运行; +2. taosAdapter 已经安装并正常运行; +3. Grafana 7.5.0 及以上的版本已经安装并正常运行。 + +记录以下信息: +1. taosAdapter 的 REST API 地址,例如:http://www.example.com:6041 +2. TDengine 集群的认证信息,包括用户名和密码,默认为root/taosdata + +### 安装 TDengine Datasource 插件 + +TDengine Datasource插件安装方式如下。 +第1步,在Web浏览器打开Grafana页面,点击页面左上角的3个横条图标,然后点击Connections按钮。 +第2步,在弹出页面的搜索栏内搜索TDengine,选择TDengine Datasource。 +第3步,点击Install按钮以安装TDengine插件。 +安装完成后,进入插件的详情页面,点击右上角的Add new data source按钮,即可进入数据源添加页面。 +进入数据源添加页面后,输入RESTful接口地址和TDengine集群的认证信息后,点击Save & test按钮,即可完成TDengine数据源的添加,如下图所示: + +![添加 TDengine 数据源](./addsource.png) + +### 创建 Dashboard + +添加TDengine数据源后,直接点击界面右上角的Build a dashboard按钮,即可创建 Dashboard。在Input Sql文本栏中输入TDengine的查询语句,便可以轻松实现监控指标的可视化,如下图所示: + +![Dashboard](./dashboard.png) + +在该示例中,查询的是由taosBenchmark --start-timestamp=1704802806146 --database= power --time-step=1000 -y写入的数据,数据库的名称为power,查询的是超级表meters 中记录的voltage,具体的SQL如下。 +```sql +select _wstart, last(voltage) from power.meters where ts>=$from and ts<=$to interval(1m) +``` + +其中,from、to为内置变量,表示从TDengine Datasource插件Dashboard获取的查询范围和时间间隔。Grafana还提供了其他内置全局变量如 `interval、org、user、timeFilter` 等,具体可以参阅Grafana的官方文档的Variables部分。可以通过group by或partition by列名来实现分组展示数据。假设要按照不同的 `groupId` 来分组展示voltage(为了避免线条太多,只查询3个分组),SQL如下。 +```sql +select _wstart, groupid, last(voltage) from power.meters where groupid < 4 and ts>=$from and ts<=$to partition by groupid interval(1m) fill(null); +``` + +然后在上图所示的 Group By Column 文本框中配置要分组的列,此处填 `groupId`。将Group By Fromat设置为 `groupId-{{groupId}}`,展示的legend名字为格式化的列名。配置好后,可如下图所示看到多条曲线。 + +![按照不同的groupId来分组展示voltage](./dashboard2.png) + +在编写和调试SQL时,可以使用Grafana提供的Query Inspector,通过它可以看到SQL的执行结果,十分方便。 + +为了简化通过Grafana对TDengine实例的运行进行检测,了解它的健康状态,TDengine还提供了一个Grafana Dashboard: TDinsight for 3.x,可在Grafana的官网直接按照此名称搜索并获取。通过Grafana导入后,即可直接使用,省去了用户自己创建Dashboard的麻烦。 + +## Looker Studio + +Looker Studio,作为Google旗下的一个功能强大的报表和商业智能工具,前身名为Google Data Studio。在2022年的Google Cloud Next大会上,Google将其更名为Looker Studio。这个工具凭借其丰富的数据可视化选项和多样化的数据连接能力,为用户提供了便捷的数据报表生成体验。用户可以根据预设的模板轻松创建数据报表,满足各种数据分析需求。 + +由于其简单易用的操作界面和庞大的生态系统支持,Looker Studio在数据分析领域受到众多数据科学家和专业人士的青睐。无论是初学者还是资深分析师,都可以利用Looker Studio快速构建美观且实用的数据报表,从而更好地洞察业务趋势、优化决策过程并提升整体运营效率。 + +### 获取 + +目前,TDengine连接器作为Looker Studio的合作伙伴连接器(partner connector),已在Looker Studio官网上线。用户访问Looker Studio的Data Source列表时,只须输入 “TDengine”进行搜索,便可轻松找到并立即使用TDengine连接器。 + +TDengine连接器兼容TDengine Cloud和TDengine Server两种类型的数据源。TDengine Cloud是涛思数据推出的全托管物联网和工业互联网大数据云服务平台,为用户提供一站式数据存储、处理和分析解决方案;而TDengine Server则是用户自行部署的本地版本,支持通过公网访问。以下内容将以TDengine Cloud为例进行介绍。 + +### 使用 + +在Looker Studio中使用TDengine连接器的步骤如下。 + +第1步,进入TDengine连接器的详情页面后,在Data Source下拉列表中选择TDengine Cloud,然后点击Next按钮,即可进入数据源配置页面。在该页面中填写以下信息,然后点击Connect按钮。 + - URL和TDengine Cloud Token,可以从TDengine Cloud的实例列表中获取。 + - 数据库名称和超级表名称。 + - 查询数据的开始时间和结束时间。 +第2步,Looker Studio会根据配置自动加载所配置的TDengine数据库下的超级表的字段和标签。 +第3步,点击页面右上角的Explore按钮,即查看从TDengine数据库中加载的数据。 +第4步,根据需求,利用Looker Studio提供的图表,进行数据可视化的配置。 + +**注意** 在第一次使用时,请根据页面提示,对Looker Studio的TDengine连接器进行访问授权。 + +## PowerBI + +Power BI是由Microsoft提供的一种商业分析工具。通过配置使用ODBC连接器,Power BI可以快速访问TDengine的数据。用户可以将标签数据、原始时序数据或按时间聚合后的时序数据从TDengine导入到Power BI,制作报表或仪表盘,整个过程不需要任何代码编写过程。 + +### 前置条件 + +安装完成Power BI Desktop软件并运行(如未安装,请从其官方地址下载最新的Windows操作系统X64版本)。 + +### 安装 ODBC 驱动 + +从TDengine官网下载最新的Windows操作系统X64客户端驱动程序,并安装在运行Power BI的机器上。安装成功后可在“ODBC数据源(64位)”管理工具中看到 TAOS_ODBC_DSN”驱动程序。 + +### 配置ODBC数据源 + +配置ODBC数据源的操作步骤如下。 + +第1步,在Windows操作系统的开始菜单中搜索并打开“ODBC数据源(64位)”管理工具。 +第2步,点击“用户DSN”选项卡→“添加”按钮,进入“创建新数据源”对话框。 +第3步,选择想要添加的数据源后选择“TDengine”,点击“完成”按钮,进入TDengine ODBC数据源配置页面。填写如下必要信息。 + - DSN:数据源名称,必填,比如“MyTDengine”。 + - 连接类型:勾选“WebSocket”复选框。 + - 服务地址:输入“taos://127.0.0.1:6041”。 + - 数据库:表示需要连接的数据库,可选,比如“test”。 + - 用户名:输入用户名,如果不填,默认为“root”。 + - 密码:输入用户密码,如果不填,默认为“taosdata”。 +第4步,点击“测试连接”按钮,测试连接情况,如果成功连接,则会提示“成功连接到taos://root:taosdata@127.0.0.1:6041”。 +第5步,点击“确定”按钮,即可保存配置并退出。 + +### 导入TDengine数据到Power BI + +将TDengine数据导入Power BI的操作步骤如下。 + +第1步,打开Power BI并登录后,点击“主页”→“获取数据”→“其他”→“ODBC”→“连接”,添加数据源。 +第2步,选择刚才创建的数据源名称,比如“MyTDengine”,点击“确定”按钮。在弹出的“ODBC驱动程序”对话框中,在左侧导航栏中点击“默认或自定义”→“连接”按钮,即可连接到配置好的数据源。进入“导航器”后,可以浏览对应数据库的数据表并加载。 +第3步,如果需要输入SQL,则可以点击“高级选项”选项卡,在展开的对话框中输入并加载数据。 + +为了充分发挥Power BI在分析TDengine中数据方面的优势,用户需要先理解维度、度量、窗口切分查询、数据切分查询、时序和相关性等核心概念,之后通过自定义的SQL导入数据。 +- 维度:通常是分类(文本)数据,描述设备、测点、型号等类别信息。在TDengine的超级表中,使用标签列存储数据的维度信息,可以通过形如“select distinct tbname, tag1, tag2 from supertable”的SQL语法快速获得维度信息。 +- 度量:可以用于进行计算的定量(数值)字段,常见计算有求和、取平均值和最小值等。如果测点的采集周期为1s,那么一年就有3000多万条记录,把这些数据全部导入Power BI会严重影响其执行效率。在TDengine中,用户可以使用数据切分查询、窗口切分查询等语法,结合与窗口相关的伪列,把降采样后的数据导入Power BI中,具体语法请参阅TDengine官方文档的特色查询功能部分。 +- 窗口切分查询:比如温度传感器每秒采集一次数据,但须查询每隔10min的温度平均值,在这种场景下可以使用窗口子句来获得需要的降采样查询结果,对应的SQL形如`select tbname, _wstart date,avg(temperature) temp from table interval(10m)`,其中,_wstart是伪列,表示时间窗口起始时间,10m表示时间窗口的持续时间,avg(temperature)表示时间窗口内的聚合值。 +- 数据切分查询:如果需要同时获取很多温度传感器的聚合数值,可对数据进行切分,然后在切分出的数据空间内进行一系列的计算,对应的SQL形如 `partition by part_list`。数据切分子句最常见的用法是在超级表查询中按标签将子表数据进行切分,将每个子表的数据独立出来,形成一条条独立的时间序列,方便针对各种时序场景的统计分析。 +- 时序:在绘制曲线或者按照时间聚合数据时,通常需要引入日期表。日期表可以从Excel表格中导入,也可以在TDengine中执行SQL获取,例如 `select _wstart date, count(*) cnt from test.meters where ts between A and B interval(1d) fill(0)`,其中fill字句表示数据缺失情况下的填充模式,伪列_wstart则为要获取的日期列。 +- 相关性:告诉数据之间如何关联,如度量和维度可以通过tbname列关联在一起,日期表和度量则可以通过date列关联,配合形成可视化报表。 + +### 智能电表样例 + +TDengine采用了一种独特的数据模型,以优化时序数据的存储和查询性能。该模型利用超级表作为模板,为每台设备创建一张独立的表。每张表在设计时考虑了高度的可扩展性,最多可包含4096个数据列和128个标签列。这种设计使得TDengine能够高效地处理大量时序数据,同时保持数据的灵活性和易用性。 + +以智能电表为例,假设每块电表每秒产生一条记录,那么每天将产生86 400条记录。对于1000块智能电表来说,每年产生的记录将占用大约600GB的存储空间。面对如此庞大的数据量,Power BI等商业智能工具在数据分析和可视化方面发挥着重要作用。 + +在Power BI中,用户可以将TDengine表中的标签列映射为维度列,以便对数据进行分组和筛选。同时,数据列的聚合结果可以导入为度量列,用于计算关键指标和生成报表。通过这种方式,Power BI能够帮助决策者快速获取所需的信息,深入了解业务运营情况,从而制定更加明智的决策。 + +根据如下步骤,便可以体验通过Power BI生成时序数据报表的功能。 +第1步,使用TDengine的taosBenchMark快速生成1000块智能电表3天的数据,采集频率为1s。 + ```shell + taosBenchmark-t1000-n259200-S1000-H200-y + ``` +第2步,导入维度数据。在Power BI中导入表的标签列,取名为tags,通过如下SQL获取超级表下所有智能电表的标签数据。 + ```sql + selectdistincttbnamedevice,groupId,locationfromtest.meters + ``` +第3步,导入度量数据。在Power BI中,按照1小时的时间窗口,导入每块智能电表的电流均值、电压均值、相位均值,取名为data,SQL如下。 + ```sql + 第3步,导入度量数据。在Power BI中,按照1小时的时间窗口,导入每块智能电表的电流均值、电压均值、相位均值,取名为data,SQL如下。 + ``` +第4步,导入日期数据。按照1天的时间窗口,获得时序数据的时间范围及数据计数,SQL如下。需要在Power Query编辑器中将date列的格式从“文本”转化为“日期”。 + ```sql + select_wstartdate,count(*)fromtest.metersinterval(1d)havingcount(*)>0 + ``` +第5步,建立维度和度量的关联关系。打开模型视图,建立表tags和data的关联关系,将tbname设置为关联数据列。 +第6步,建立日期和度量的关联关系。打开模型视图,建立数据集date和data的关联关系,关联的数据列为date和datatime。 +第7步,制作报告。在柱状图、饼图等控件中使用这些数据。 + +由于TDengine处理时序数据的超强性能,使得用户在数据导入及每日定期刷新数据时,都可以得到非常好的体验。更多有关Power BI视觉效果的构建方法,请参照Power BI的官方文档。 + +## 永洪 BI + +永洪 BI 是一个专为各种规模企业打造的全业务链大数据分析解决方案,旨在帮助用户轻松发掘大数据价值,获取深入的洞察力。该平台以其灵活性和易用性而广受好评,无论企业规模大小,都能从中受益。 + +为了实现与 TDengine 的高效集成,永洪 BI 提供了 JDBC 连接器。用户只须按照简单的步骤配置数据源,即可将 TDengine 作为数据源添加到永洪BI中。这一过程不仅快速便捷,还能确保数据的准确性和稳定性。 + +一旦数据源配置完成,永洪BI便能直接从TDengine中读取数据,并利用其强大的数据处理和分析功能,为用户提供丰富的数据展示、分析和预测能力。这意味着用户无须编写复杂的代码或进行烦琐的数据转换工作,即可轻松获取所需的业务洞察。 + +### 安装永洪 BI + +确保永洪 BI 已经安装并运行(如果未安装,请到永洪科技官方下载页面下载)。 + +### 安装JDBC驱动 + +从 maven.org 下载 TDengine JDBC 连接器文件 “taos-jdbcdriver-3.2.7-dist.jar”,并安装在永洪 BI 的机器上。 + +### 配置JDBC数据源 + +配置JDBC数据源的步骤如下。 + +第1步,在打开的永洪BI中点击“添加数据源”按钮,选择SQL数据源中的“GENERIC”类型。 +第2步,点击“选择自定义驱动”按钮,在“驱动管理”对话框中点击“驱动列表”旁边的“+”,输入名称“MyTDengine”。然后点击“上传文件”按钮,上传刚刚下载的TDengine JDBC连接器文件“taos-jdbcdriver-3.2.7-dist.jar”,并选择“com.taosdata.jdbc. +rs.RestfulDriver”驱动,最后点击“确定”按钮,完成驱动添加步骤。 +第3步,复制下面的内容到“URL”字段。 + ```text + jdbc:TAOS-RS://127.0.0.1:6041?user=root&password=taosdata + ``` +第4步,在“认证方式”中点击“无身份认证”单选按钮。 +第5步,在数据源的高级设置中修改“Quote 符号”的值为反引号(`)。 +第6步,点击“测试连接”按钮,弹出“测试成功”对话框。点击“保存”按钮,输入“MyTDengine”来保存TDengine数据源。 + +### 创建TDengine数据集 + +创建TDengine数据集的步骤如下。 + +第1步,在永洪BI中点击“添加数据源”按钮,展开刚刚创建的数据源,并浏览TDengine中的超级表。 +第2步,可以将超级表的数据全部加载到永洪BI中,也可以通过自定义SQL导入部分数据。 +第3步,当勾选“数据库内计算”复选框时,永洪BI将不再缓存TDengine的时序数据,并在处理查询时将SQL请求发送给TDengine直接处理。 + +当导入数据后,永洪BI会自动将数值类型设置为“度量”列,将文本类型设置为“维度”列。而在TDengine的超级表中,由于将普通列作为数据的度量,将标签列作为数据的维度,因此用户可能需要在创建数据集时更改部分列的属性。TDengine在支持标准SQL的基础之上还提供了一系列满足时序业务场景需求的特色查询语法,例如数据切分查询、窗口切分查询等,具体操作步骤请参阅TDengine的官方文档。通过使用这些特色查询,当永洪BI将SQL查询发送到TDengine时,可以大大提高数据访问速度,减少网络传输带宽。 + +在永洪BI中,你可以创建“参数”并在SQL中使用,通过手动、定时的方式动态执行这些SQL,即可实现可视化报告的刷新效果。如下SQL可以从TDengine实时读取数据。 +```sql +select _wstart ws, count(*) cnt from supertable where tbname=?{metric} and ts = ?{from} and ts < ?{to} interval(?{interval}) +``` + +其中: +1. `_wstart`:表示时间窗口起始时间。 +2. `count(*)`:表示时间窗口内的聚合值。 +3. `?{interval}`:表示在 SQL 语句中引入名称为 `interval` 的参数,当 BI 工具查询数据时,会给 `interval` 参数赋值,如果取值为 1m,则表示按照 1 分钟的时间窗口降采样数据。 +4. `?{metric}`:该参数用来指定查询的数据表名称,当在 BI 工具中把某个“下拉参数组件”的 ID 也设置为 metric 时,该“下拉参数组件”的被选择项将会和该参数绑定在一起,实现动态选择的效果。 +5. `?{from}` 和 `?{to}`:这两个参数用来表示查询数据集的时间范围,可以与“文本参数组件”绑定。 +您可以在 BI 工具的“编辑参数”对话框中修改“参数”的数据类型、数据范围、默认取值,并在“可视化报告”中动态设置这些参数的值。 + +### 21.4.5 制作可视化报告 + +制作可视化报告的步骤如下。 + +1. 在永洪 BI 工具中点击“制作报告”,创建画布。 +2. 拖动可视化组件到画布中,例如“表格组件”。 +3. 在“数据集”侧边栏中选择待绑定的数据集,将数据列中的“维度”和“度量”按需绑定到“表格组件”。 +4. 点击“保存”后,即可查看报告。 +5. 更多有关永洪 BI 工具的信息,请查询永洪科技官方帮助文档。 + diff --git a/docs/zh/08-develop/addsource.png b/docs/zh/08-develop/addsource.png new file mode 100644 index 0000000000..f041ac61bc Binary files /dev/null and b/docs/zh/08-develop/addsource.png differ diff --git a/docs/zh/08-develop/dashboard.png b/docs/zh/08-develop/dashboard.png new file mode 100644 index 0000000000..e932f2ed62 Binary files /dev/null and b/docs/zh/08-develop/dashboard.png differ diff --git a/docs/zh/08-develop/dashboard2.png b/docs/zh/08-develop/dashboard2.png new file mode 100644 index 0000000000..aa1ad22f93 Binary files /dev/null and b/docs/zh/08-develop/dashboard2.png differ diff --git a/docs/zh/08-develop/03-insert-data/highvolume.webp b/docs/zh/08-develop/highvolume.webp similarity index 100% rename from docs/zh/08-develop/03-insert-data/highvolume.webp rename to docs/zh/08-develop/highvolume.webp diff --git a/docs/zh/08-connector/02-rest-api.mdx b/docs/zh/14-reference/05-connector/02-rest-api.mdx similarity index 100% rename from docs/zh/08-connector/02-rest-api.mdx rename to docs/zh/14-reference/05-connector/02-rest-api.mdx diff --git a/docs/zh/08-connector/10-cpp.mdx b/docs/zh/14-reference/05-connector/10-cpp.mdx similarity index 100% rename from docs/zh/08-connector/10-cpp.mdx rename to docs/zh/14-reference/05-connector/10-cpp.mdx diff --git a/docs/zh/08-connector/14-java.mdx b/docs/zh/14-reference/05-connector/14-java.mdx similarity index 100% rename from docs/zh/08-connector/14-java.mdx rename to docs/zh/14-reference/05-connector/14-java.mdx diff --git a/docs/zh/08-connector/20-go.mdx b/docs/zh/14-reference/05-connector/20-go.mdx similarity index 100% rename from docs/zh/08-connector/20-go.mdx rename to docs/zh/14-reference/05-connector/20-go.mdx diff --git a/docs/zh/08-connector/26-rust.mdx b/docs/zh/14-reference/05-connector/26-rust.mdx similarity index 98% rename from docs/zh/08-connector/26-rust.mdx rename to docs/zh/14-reference/05-connector/26-rust.mdx index dada93ce32..2cdfdc9e41 100644 --- a/docs/zh/08-connector/26-rust.mdx +++ b/docs/zh/14-reference/05-connector/26-rust.mdx @@ -8,10 +8,6 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Preparation from "./_preparation.mdx" -import RustInsert from "../08-develop/03-insert-data/_rust_sql.mdx" -import RustBind from "../08-develop/03-insert-data/_rust_stmt.mdx" -import RustSml from "../08-develop/03-insert-data/_rust_schemaless.mdx" -import RustQuery from "../08-develop/04-query-data/_rust.mdx" import RequestId from "./_request_id.mdx"; [![Crates.io](https://img.shields.io/crates/v/taos)](https://crates.io/crates/taos) ![Crates.io](https://img.shields.io/crates/d/taos) [![docs.rs](https://img.shields.io/docsrs/taos)](https://docs.rs/taos) diff --git a/docs/zh/08-connector/30-python.mdx b/docs/zh/14-reference/05-connector/30-python.mdx similarity index 100% rename from docs/zh/08-connector/30-python.mdx rename to docs/zh/14-reference/05-connector/30-python.mdx diff --git a/docs/zh/08-connector/35-node.mdx b/docs/zh/14-reference/05-connector/35-node.mdx similarity index 100% rename from docs/zh/08-connector/35-node.mdx rename to docs/zh/14-reference/05-connector/35-node.mdx diff --git a/docs/zh/08-connector/40-csharp.mdx b/docs/zh/14-reference/05-connector/40-csharp.mdx similarity index 100% rename from docs/zh/08-connector/40-csharp.mdx rename to docs/zh/14-reference/05-connector/40-csharp.mdx diff --git a/docs/zh/08-connector/43-r-lang.mdx b/docs/zh/14-reference/05-connector/43-r-lang.mdx similarity index 97% rename from docs/zh/08-connector/43-r-lang.mdx rename to docs/zh/14-reference/05-connector/43-r-lang.mdx index f2a74dcd7f..e8929e5ca0 100644 --- a/docs/zh/08-connector/43-r-lang.mdx +++ b/docs/zh/14-reference/05-connector/43-r-lang.mdx @@ -7,7 +7,7 @@ title: R Language Connector import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -import Rdemo from "../08-develop/01-connect/_connect_r.mdx" +import Rdemo from "../../08-develop/01-connect/_connect_r.mdx" 通过 R 语言中的 RJDBC 库可以使 R 语言程序支持访问 TDengine 数据。以下是安装过程、配置过程以及 R 语言示例代码。 diff --git a/docs/zh/08-connector/45-php.mdx b/docs/zh/14-reference/05-connector/45-php.mdx similarity index 100% rename from docs/zh/08-connector/45-php.mdx rename to docs/zh/14-reference/05-connector/45-php.mdx diff --git a/docs/zh/08-connector/50-odbc.mdx b/docs/zh/14-reference/05-connector/50-odbc.mdx similarity index 100% rename from docs/zh/08-connector/50-odbc.mdx rename to docs/zh/14-reference/05-connector/50-odbc.mdx diff --git a/docs/zh/08-connector/_01-error-code.md b/docs/zh/14-reference/05-connector/_01-error-code.md similarity index 100% rename from docs/zh/08-connector/_01-error-code.md rename to docs/zh/14-reference/05-connector/_01-error-code.md diff --git a/docs/zh/08-connector/_05-schemaless.mdx b/docs/zh/14-reference/05-connector/_05-schemaless.mdx similarity index 100% rename from docs/zh/08-connector/_05-schemaless.mdx rename to docs/zh/14-reference/05-connector/_05-schemaless.mdx diff --git a/docs/zh/08-connector/_category_.yml b/docs/zh/14-reference/05-connector/_category_.yml similarity index 100% rename from docs/zh/08-connector/_category_.yml rename to docs/zh/14-reference/05-connector/_category_.yml diff --git a/docs/zh/08-connector/_linux_install.mdx b/docs/zh/14-reference/05-connector/_linux_install.mdx similarity index 100% rename from docs/zh/08-connector/_linux_install.mdx rename to docs/zh/14-reference/05-connector/_linux_install.mdx diff --git a/docs/zh/08-connector/_macos_install.mdx b/docs/zh/14-reference/05-connector/_macos_install.mdx similarity index 100% rename from docs/zh/08-connector/_macos_install.mdx rename to docs/zh/14-reference/05-connector/_macos_install.mdx diff --git a/docs/zh/08-connector/_preparation.mdx b/docs/zh/14-reference/05-connector/_preparation.mdx similarity index 100% rename from docs/zh/08-connector/_preparation.mdx rename to docs/zh/14-reference/05-connector/_preparation.mdx diff --git a/docs/zh/08-connector/_request_id.mdx b/docs/zh/14-reference/05-connector/_request_id.mdx similarity index 100% rename from docs/zh/08-connector/_request_id.mdx rename to docs/zh/14-reference/05-connector/_request_id.mdx diff --git a/docs/zh/08-connector/_verify_linux.mdx b/docs/zh/14-reference/05-connector/_verify_linux.mdx similarity index 100% rename from docs/zh/08-connector/_verify_linux.mdx rename to docs/zh/14-reference/05-connector/_verify_linux.mdx diff --git a/docs/zh/08-connector/_verify_macos.mdx b/docs/zh/14-reference/05-connector/_verify_macos.mdx similarity index 100% rename from docs/zh/08-connector/_verify_macos.mdx rename to docs/zh/14-reference/05-connector/_verify_macos.mdx diff --git a/docs/zh/08-connector/_verify_windows.mdx b/docs/zh/14-reference/05-connector/_verify_windows.mdx similarity index 100% rename from docs/zh/08-connector/_verify_windows.mdx rename to docs/zh/14-reference/05-connector/_verify_windows.mdx diff --git a/docs/zh/08-connector/_windows_install.mdx b/docs/zh/14-reference/05-connector/_windows_install.mdx similarity index 100% rename from docs/zh/08-connector/_windows_install.mdx rename to docs/zh/14-reference/05-connector/_windows_install.mdx diff --git a/docs/zh/08-connector/assets/odbc-check-data.webp b/docs/zh/14-reference/05-connector/assets/odbc-check-data.webp similarity index 100% rename from docs/zh/08-connector/assets/odbc-check-data.webp rename to docs/zh/14-reference/05-connector/assets/odbc-check-data.webp diff --git a/docs/zh/08-connector/assets/odbc-native-config-zh.webp b/docs/zh/14-reference/05-connector/assets/odbc-native-config-zh.webp similarity index 100% rename from docs/zh/08-connector/assets/odbc-native-config-zh.webp rename to docs/zh/14-reference/05-connector/assets/odbc-native-config-zh.webp diff --git a/docs/zh/08-connector/assets/odbc-ws-config-zh.webp b/docs/zh/14-reference/05-connector/assets/odbc-ws-config-zh.webp similarity index 100% rename from docs/zh/08-connector/assets/odbc-ws-config-zh.webp rename to docs/zh/14-reference/05-connector/assets/odbc-ws-config-zh.webp diff --git a/docs/zh/08-connector/connector.webp b/docs/zh/14-reference/05-connector/connector.webp similarity index 100% rename from docs/zh/08-connector/connector.webp rename to docs/zh/14-reference/05-connector/connector.webp diff --git a/docs/zh/08-connector/index.md b/docs/zh/14-reference/05-connector/index.md similarity index 100% rename from docs/zh/08-connector/index.md rename to docs/zh/14-reference/05-connector/index.md diff --git a/docs/zh/08-connector/tdengine-jdbc-connector.webp b/docs/zh/14-reference/05-connector/tdengine-jdbc-connector.webp similarity index 100% rename from docs/zh/08-connector/tdengine-jdbc-connector.webp rename to docs/zh/14-reference/05-connector/tdengine-jdbc-connector.webp diff --git a/docs/zh/14-reference/09-support-platform/index.md b/docs/zh/14-reference/05-supported.md similarity index 99% rename from docs/zh/14-reference/09-support-platform/index.md rename to docs/zh/14-reference/05-supported.md index ba3b3deee1..18aec5f507 100644 --- a/docs/zh/14-reference/09-support-platform/index.md +++ b/docs/zh/14-reference/05-supported.md @@ -1,4 +1,5 @@ --- +sidebar_label: 支持平台 title: 支持平台列表 description: "TDengine 服务端、客户端和连接器支持的平台列表" --- diff --git a/docs/zh/14-reference/09-support-platform/_category_.yml b/docs/zh/14-reference/09-support-platform/_category_.yml deleted file mode 100644 index ce2aa5213b..0000000000 --- a/docs/zh/14-reference/09-support-platform/_category_.yml +++ /dev/null @@ -1 +0,0 @@ -label: 支持平台列表 diff --git a/docs/zh/14-reference/12-config/_category_.yml b/docs/zh/14-reference/12-config/_category_.yml deleted file mode 100644 index 8d3cfcc8d0..0000000000 --- a/docs/zh/14-reference/12-config/_category_.yml +++ /dev/null @@ -1 +0,0 @@ -label: 配置参数 \ No newline at end of file diff --git a/docs/zh/14-reference/12-config/index.md b/docs/zh/14-reference/12-config/index.md deleted file mode 100755 index 9dced94799..0000000000 --- a/docs/zh/14-reference/12-config/index.md +++ /dev/null @@ -1,977 +0,0 @@ ---- -title: 配置参数 -description: "TDengine 客户端和服务配置列表" ---- - -## 为服务端指定配置文件 - -TDengine 系统后台服务由 taosd 提供,可以在配置文件 taos.cfg 里修改配置参数,以满足不同场景的需求。在 Linux 系统上,配置文件的缺省位置在 `/etc/taos` 目录,在 Windows 系统上缺省位置在 `C:\TDengine` 。可以通过 taosd 命令行执行参数 -c 指定配置文件所在目录。比如,在 Linux 系统上可以指定配置文件位于 `/home/user` 这个目录: - -``` -taosd -c /home/user -``` - -另外可以使用 `-C` 显示当前服务器配置参数: - -``` -taosd -C -``` - -## 为客户端指定配置文件 - -TDengine 系统的前台交互客户端应用程序为 taos,以及应用驱动,它可以与 taosd 共享同一个配置文件 taos.cfg,也可以使用单独指定配置文件。运行 taos 时,使用参数-c 指定配置文件目录,如: - -``` -taos -c /home/cfg -``` - -表示使用/home/cfg/目录下的 taos.cfg 配置文件中的参数,缺省目录是/etc/taos。 另外可以使用 `-C` 显示当前服务器配置参数: - -```bash -taos -C -``` - -更多 taos 的使用方法请见帮助信息 `taos --help`。 - -## 配置参数详细列表 - -:::note -本节内容覆盖产品的配置参数,适用于服务端的参数按其对产品行为的影响进行分类,这其中有部分参数也同时适用于客户端;但有少量参数仅适用于客户端,这部分参数进行了单独归类。 - -::: - -:::note -配置文件参数修改后,需要重启*taosd*服务,或客户端应用才能生效。 - -::: - -## 连接相关 - -### firstEp - -| 属性 | 说明 | -| -------- | -------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | taosd 或者 taos 启动时,主动连接的集群中首个 dnode 的 endpoint | -| 缺省值 | localhost:6030 | - -### secondEp - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | taosd 或者 taos 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint | -| 缺省值 | 无 | - -### fqdn - -| 属性 | 说明 | -| -------- | ----------------------------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 数据节点的 FQDN。如果习惯 IP 地址访问,可设置为该节点的 IP 地址。 | -| 缺省值 | 缺省为操作系统配置的第一个 hostname。 | -| 补充说明 | 这个参数值的长度需要控制在 96 个字符以内。 | - -### serverPort - -| 属性 | 说明 | -| -------- | ------------------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | taosd 启动后,对外服务的端口号 | -| 缺省值 | 6030 | - -:::note -确保集群中所有主机在端口 6030 上的 TCP 协议能够互通。(详细的端口情况请参见下表) -::: -| 协议 | 默认端口 | 用途说明 | 修改方法 | -| :--- | :------- | :----------------------------------------------- | :------------------------------------------------------------------------------------------------- | -| TCP | 6030 | 客户端与服务端之间通讯,多节点集群的节点间通讯。 | 由配置文件设置 serverPort 决定。 | -| TCP | 6041 | 客户端与服务端之间的 RESTful 通讯。 | 随 serverPort 端口变化。注意 taosAdapter 配置或有不同,请参考相应[文档](../taosadapter/)。 | -| TCP | 6043 | taosKeeper 监控服务端口。 | 随 taosKeeper 启动参数设置变化。 | -| TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化 | -| UDP | 6045 | 支持 collectd 数据接入端口。 | 随 taosAdapter 启动参数设置变化 | -| TCP | 6060 | 企业版内 Monitor 服务的网络端口。 | | - -### maxShellConns - -| 属性 | 说明 | -| -------- | ----------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 一个 dnode 容许的连接数 | -| 取值范围 | 10-50000000 | -| 缺省值 | 5000 | - -### numOfRpcSessions - -| 属性 | 说明 | -| -------- | ---------------------------- | -| 适用范围 | 客户端和服务端都适用 | -| 含义 | 一个客户端能创建的最大连接数 | -| 取值范围 | 100-100000 | -| 缺省值 | 30000 | - -### timeToGetAvailableConn - -| 属性 | 说明 | -| -------- | -------------------------- | -| 适用范围 | 客户端和服务端都适用 | -| 含义 | 获得可用连接的最长等待时间 | -| 取值范围 | 10-50000000(单位为毫秒) | -| 缺省值 | 500000 | - -## 监控相关 - -:::note -请注意,完整的监控功能需要安装并运行 `taoskeeper` 服务。taoskeeper 负责接收监控指标数据并创建 `log` 库。 - -::: - -### monitor - -| 属性 | 说明 | -| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况,包括 CPU、内存、硬盘、网络带宽的监控记录,监控信息将通过 HTTP 协议发送给由 `monitorFqdn` 和 `monitorProt` 指定的 taosKeeper 监控服务 | -| 取值范围 | 0:关闭监控服务, 1:激活监控服务。 | -| 缺省值 | 0 | - -### monitorFqdn - -| 属性 | 说明 | -| -------- | -------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | taosKeeper 监控服务的 FQDN | -| 缺省值 | 无 | - -### monitorPort - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | taosKeeper 监控服务的端口号 | -| 缺省值 | 6043 | - -### monitorInterval - -| 属性 | 说明 | -| -------- | -------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 监控数据库记录系统参数(CPU/内存)的时间间隔 | -| 单位 | 秒 | -| 取值范围 | 1-200000 | -| 缺省值 | 30 | - -### telemetryReporting - -| 属性 | 说明 | -| -------- | ------------------------ | -| 适用范围 | 客户端和服务端都适用 | -| 含义 | 是否上传 telemetry | -| 取值范围 | 0,1 0: 不上传;1:上传 | -| 缺省值 | 1 | - -### crashReporting - -| 属性 | 说明 | -| -------- | ------------------------ | -| 适用范围 | 客户端和服务端都适用 | -| 含义 | 是否上传 crash 信息 | -| 取值范围 | 0,1 0: 不上传;1:上传 | -| 缺省值 | 1 | - -## 查询相关 - -### queryPolicy - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 适用范围 | 仅客户端适用 | -| 含义 | 查询语句的执行策略 | -| 单位 | 无 | -| 缺省值 | 1 | -| 补充说明 | 1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 | - -### querySmaOptimize - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | sma index 的优化策略 | -| 单位 | 无 | -| 缺省值 | 0 | -| 补充说明 | 0: 表示不使用 sma index,永远从原始数据进行查询; 1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询 | - -### maxNumOfDistinctRes - -| 属性 | 说明 | -| -------- | -------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 允许返回的 distinct 结果最大行数 | -| 取值范围 | 默认值为 10 万,最大值 1 亿 | -| 缺省值 | 10 万 | - -### keepColumnName - -| 属性 | 说明 | -| -------- | ----------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | Last、First、LastRow 函数查询且未指定别名时,自动设置别名为列名(不含函数名),因此 order by 子句如果引用了该列名将自动引用该列对应的函数 | -| 取值范围 | 1 表示自动设置别名为列名(不包含函数名), 0 表示不自动设置别名。 | -| 缺省值 | 0 | -| 补充说明 | 当同时出现多个上述函数作用于同一列且未指定别名时,如果 order by 子句引用了该列名,将会因为多列别名相同引发列选择冲突| - -### countAlwaysReturnValue - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端适用 | -| 含义 | count/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值 | -| 取值范围 | 0:返回空行,1:返回 0 | -| 缺省值 | 1 | -| 补充说明 | 该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了TSMA时, 且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果. 注意此参数客户端和服务端值应保持一致. | - -### multiResultFunctionStarReturnTags - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | 查询超级表时,last(\*)/last_row(\*)/first(\*) 是否返回标签列;查询普通表、子表时,不受该参数影响。 | -| 取值范围 | 0:不返回标签列,1:返回标签列 | -| 缺省值 | 0 | -| 补充说明 | 该参数设置为 0 时,last(\*)/last_row(\*)/first(\*) 只返回超级表的普通列;为 1 时,返回超级表的普通列和标签列 | - -### maxTsmaCalcDelay - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | 查询时客户端可允许的tsma计算延迟, 若tsma的计算延迟大于配置值, 则该TSMA将不会被使用. | -| 取值范围 | 600s - 86400s, 即10分钟-1小时 | -| 缺省值 | 600s | - -### tsmaDataDeleteMark - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | TSMA计算的历史数据中间结果保存时间, 单位为毫秒 | -| 取值范围 | >= 3600000, 即大于等于1h | -| 缺省值 | 86400000, 即1d | - - -## 区域相关 - -### timezone - -| 属性 | 说明 | -| -------- | ------------------------------ | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 时区 | -| 缺省值 | 从系统中动态获取当前的时区设置 | - -:::info -为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix 时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。 - -在 Linux/macOS 中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如: - -``` -timezone UTC-8 -timezone GMT-8 -timezone Asia/Shanghai -``` - -均是合法的设置东八区时区的格式。但需注意,Windows 下并不支持 `timezone Asia/Shanghai` 这样的写法,而必须写成 `timezone UTC-8`。 - -时区的设置对于查询和写入 SQL 语句中非 Unix 时间戳的内容(时间戳字符串、关键词 now 的解析)产生影响。例如: - -```sql -SELECT count(*) FROM table_name WHERE TS<'2019-04-11 12:01:08'; -``` - -在东八区,SQL 语句等效于 - -```sql -SELECT count(*) FROM table_name WHERE TS<1554955268000; -``` - -在 UTC 时区,SQL 语句等效于 - -```sql -SELECT count(*) FROM table_name WHERE TS<1554984068000; -``` - -为了避免使用字符串时间格式带来的不确定性,也可以直接使用 Unix 时间戳。此外,还可以在 SQL 语句中使用带有时区的时间戳字符串,例如:RFC3339 格式的时间戳字符串,2013-04-12T15:52:01.123+08:00 或者 ISO-8601 格式时间戳字符串 2013-04-12T15:52:01.123+0800。上述两个字符串转化为 Unix 时间戳不受系统所在时区的影响。 - -::: - -### locale - -| 属性 | 说明 | -| -------- | ----------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 系统区位信息及编码格式 | -| 缺省值 | 系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 | - -:::info -TDengine 为存储中文、日文、韩文等非 ASCII 编码的宽字符,提供一种专门的字段类型 nchar。写入 nchar 字段的数据将统一采用 UCS4-LE 格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用 nchar 字段来存储诸如中文、日文、韩文等非 ASCII 字符,需要正确设置客户端的编码格式。 - -客户端的输入的字符均采用操作系统当前默认的编码格式,在 Linux/macOS 系统上多为 UTF-8,部分中文系统编码则可能是 GB18030 或 GBK 等。在 docker 环境中默认的编码是 POSIX。在中文版 Windows 系统中,编码则是 CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证 nchar 中的数据正确转换为 UCS4-LE 编码格式。 - -在 Linux/macOS 中 locale 的命名规则为: \<语言>_\<地区>.\<字符集编码> 如:zh_CN.UTF-8,zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux/macOS 可以通过设置 locale 来确定系统的字符编码,由于 Windows 使用的 locale 中不是 POSIX 标准的 locale 格式,因此在 Windows 下需要采用另一个配置参数 charset 来指定字符编码。在 Linux/macOS 中也可以使用 charset 来指定字符编码。 - -::: - -### charset - -| 属性 | 说明 | -| -------- | ----------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 字符集编码 | -| 缺省值 | 系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 | - -:::info -如果配置文件中不设置 charset,在 Linux/macOS 中,taos 在启动时候,自动读取系统当前的 locale 信息,并从 locale 信息中解析提取 charset 编码格式。如果自动读取 locale 信息失败,则尝试读取 charset 配置,如果读取 charset 配置也失败,则中断启动过程。 - -在 Linux/macOS 中,locale 信息包含了字符编码信息,因此正确设置了 Linux/macOS 的 locale 以后可以不用再单独设置 charset。例如: - -``` -locale zh_CN.UTF-8 -``` - -在 Windows 系统中,无法从 locale 获取系统当前编码。如果无法从配置文件中读取字符串编码信息,taos 默认设置为字符编码为 CP936。其等效在配置文件中添加如下配置: - -``` -charset CP936 -``` - -如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。 - -在 Linux/macOS 中,如果用户同时设置了 locale 和字符集编码 charset,并且 locale 和 charset 的不一致,后设置的值将覆盖前面设置的值。 - -``` -locale zh_CN.UTF-8 -charset GBK -``` - -则 charset 的有效值是 GBK。 - -``` -charset GBK -locale zh_CN.UTF-8 -``` - -charset 的有效值是 UTF-8。 - -::: - -## 存储相关 - -### dataDir - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 数据文件目录,所有的数据文件都将写入该目录 | -| 缺省值 | /var/lib/taos | -| 补充说明 | [多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8) 功能需要与 [KEEP](https://docs.taosdata.com/taos-sql/database/#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E) 参数配合使用 | - -### tempDir - -| 属性 | 说明 | -| -------- | ------------------------------------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | 该参数指定所有系统运行过程中的临时文件生成的目录 | -| 缺省值 | /tmp | - -### minimalTmpDirGB - -| 属性 | 说明 | -| -------- | ------------------------------------------------ | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | tempDir 所指定的临时文件目录所需要保留的最小空间 | -| 单位 | GB | -| 缺省值 | 1.0 | - -### minimalDataDirGB - -| 属性 | 说明 | -| -------- | ---------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | dataDir 指定的时序数据存储目录所需要保留的最小 | -| 单位 | GB | -| 缺省值 | 2.0 | - -### metaCacheMaxSize - -| 属性 | 说明 | -| -------- | ------------------------------------ | -| 适用范围 | 仅客户端适用 | -| 含义 | 指定单个客户端元数据缓存大小的最大值 | -| 单位 | MB | -| 缺省值 | -1 (无限制) | - -## 集群相关 - -### supportVnodes - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | dnode 支持的最大 vnode 数目 | -| 取值范围 | 0-4096 | -| 缺省值 | CPU 核数的 2 倍 + 5 | - -## 性能调优 - -### numOfCommitThreads - -| 属性 | 说明 | -| -------- | ---------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 设置写入线程的最大数量 | -| 取值范围 | 0-1024 | -| 缺省值 | 4 | - -## 日志相关 - -### logDir - -| 属性 | 说明 | -| -------- | -------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 日志文件目录,客户端和服务器的运行日志将写入该目录 | -| 缺省值 | /var/log/taos | - -### minimalLogDirGB - -| 属性 | 说明 | -| -------- | ------------------------------------------------------ | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志 | -| 单位 | GB | -| 缺省值 | 1.0 | - -### numOfLogLines - -| 属性 | 说明 | -| -------- | ---------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 单个日志文件允许的最大行数。 | -| 缺省值 | 10,000,000 | - -### asyncLog - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 日志写入模式 | -| 取值范围 | 0:同步、1:异步 | -| 缺省值 | 1 | - -### logKeepDays - -| 属性 | 说明 | -| -------- | ----------------------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 日志文件的最长保存时间 | -| 单位 | 天 | -| 缺省值 | 0 | -| 补充说明 | 大于 0 时,日志文件会被重命名为 taosdlog.xxx,其中 xxx 为日志文件最后修改的时间戳。 | - -### slowLogThreshold - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | 指定慢查询门限值,大于等于门限值认为是慢查询 | -| 单位 | 秒 | -| 缺省值 | 3 | -| 补充说明 | 每个客户端中所有慢查询会被记录在日志目录下的taosSlowLog文件中 | - -### slowLogScope - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | 指定启动记录哪些类型的慢查询 | -| 可选值 | ALL, QUERY, INSERT, OTHERS, NONE | -| 缺省值 | ALL | -| 补充说明 | 默认记录所有类型的慢查询,可通过配置只记录某一类型的慢查询 | - -### debugFlag - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 运行日志开关 | -| 取值范围 | 131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志) | -| 缺省值 | 131 或 135(不同模块有不同的默认值) | - -### tmrDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 定时器模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### uDebugFlag - -| 属性 | 说明 | -| -------- | ---------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 共用功能模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### rpcDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | rpc 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### jniDebugFlag - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅客户端适用 | -| 含义 | jni 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### qDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | query 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### cDebugFlag - -| 属性 | 说明 | -| -------- | --------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | client 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### dDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | dnode 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | 135 | - -### vDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | vnode 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### mDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | mnode 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | 135 | - -### wDebugFlag - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | wal 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | 135 | - -### sDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | sync 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | 135 | - -### tsdbDebugFlag - -| 属性 | 说明 | -| -------- | ------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | tsdb 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### tqDebugFlag - -| 属性 | 说明 | -| -------- | ----------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | tq 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### fsDebugFlag - -| 属性 | 说明 | -| -------- | ----------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | fs 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### udfDebugFlag - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | UDF 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### smaDebugFlag - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | sma 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### idxDebugFlag - -| 属性 | 说明 | -| -------- | -------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | index 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -### tdbDebugFlag - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | tdb 模块的日志开关 | -| 取值范围 | 同上 | -| 缺省值 | | - -## Schemaless 相关 - -### smlChildTableName - -| 属性 | 说明 | -| -------- | ------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | schemaless 自定义的子表名的 key | -| 类型 | 字符串 | -| 缺省值 | 无 - -### smlAutoChildTableNameDelimiter - -| 属性 | 说明 | -| -------- | ------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | schemaless tag之间的连接符,连起来作为子表名 | -| 类型 | 字符串 | -| 缺省值 | 无 | - -### smlTagName - -| 属性 | 说明 | -| -------- | ------------------------------------ | -| 适用范围 | 仅客户端适用 | -| 含义 | schemaless tag 为空时默认的 tag 名字 | -| 类型 | 字符串 | -| 缺省值 | \_tag_null | - -### smlDataFormat - -| 属性 | 说明 | -| -------- | -------------------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | schemaless 列数据是否顺序一致,从3.0.3.0开始,该配置废弃 | -| 值域 | 0:不一致;1: 一致 | -| 缺省值 | 0 | - -### smlTsDefaultName - -| 属性 | 说明 | -| -------- | -------------------------------------------- | -| 适用范围 | 仅客户端适用 | -| 含义 | schemaless自动建表的时间列名字通过该配置设置 | -| 类型 | 字符串 | -| 缺省值 | _ts | - -## 其他 - -### enableCoreFile - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | 是否开启服务 crash 时生成 core 文件 | -| 取值范围 | 0:否,1:是 | -| 缺省值 | 1 | -| 补充说明 | 不同的启动方式,生成 core 文件的目录如下:1、systemctl start taosd 启动:生成的 core 在根目录下
2、手动启动,就在 taosd 执行目录下。 | - -### enableScience - -| 属性 | 说明 | -| -------- | ---------------------------- | -| 适用范围 | 仅客户端 TAOS-CLI 适用 | -| 含义 | 是否开启科学计数法显示浮点数 | -| 取值范围 | 0:否,1:是 | -| 缺省值 | 0 | - -### udf - -| 属性 | 说明 | -| -------- | ------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | 是否启动 udf 服务 | -| 取值范围 | 0: 不启动;1:启动 | -| 缺省值 | 1 | - -### ttlChangeOnWrite - -| 属性 | 说明 | -| -------- | ------------------------------------ | -| 适用范围 | 仅服务端适用 | -| 含义 | ttl 到期时间是否伴随表的修改操作改变 | -| 取值范围 | 0: 不改变;1:改变 | -| 缺省值 | 0 | - -### tmqMaxTopicNum - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 订阅最多可建立的 topic 数量 | -| 取值范围 | 1-10000 | -| 缺省值 | 20 | - -### maxTsmaNum - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 集群内可创建的TSMA个数 | -| 取值范围 | 0-3 | -| 缺省值 | 3 | - -## 压缩参数 - -### compressMsgSize - -| 属性 | 说明 | -| -------- | ------------------------------------------------------------------------------- | -| 适用于 | 服务端和客户端均适用 | -| 含义 | 是否对 RPC 消息进行压缩 | -| 取值范围 | -1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩 | -| 缺省值 | -1 | - -### fPrecision -FLOAT 类型压缩精度控制: - -| 属性 | 说明 | -| -------- | -------------------------------- | -| 适用范围 | 服务器端 | -| 含义 | 设置 float 类型浮点数压缩精度 | -| 取值范围 | 0.1 ~ 0.00000001 | -| 缺省值 | 0.00000001 | -| 补充说明 | 小于此值的浮点数尾数部分将被截取 | - -### dPrecision -| 属性 | 说明 | -| -------- | -------------------------------- | -| 适用范围 | 服务器端 | -| 含义 | 设置 double 类型浮点数压缩精度 | -| 取值范围 | 0.1 ~ 0.0000000000000001 | -| 缺省值 | 0.0000000000000001 | -| 补充说明 | 小于此值的浮点数尾数部分将被截取 | - -### lossyColumn - -| 属性 | 说明 | -| -------- | -------------------------------- | -| 适用范围 | 服务器端 | -| 含义 | 对 float 和/或 double 类型启用 TSZ 有损压缩 | -| 取值范围 | float, double | -| 缺省值 | none:表示关闭无损压缩 | - -**补充说明** -1. 在 3.2.0.0 ~ 3.3.0.0(不包含)版本生效,启用该参数后不能回退到升级前的版本 -2. TSZ 压缩算法是通过数据预测技术完成的压缩,所以更适合有规律变化的数据 -3. TSZ 压缩时间会更长一些,如果您的服务器 CPU 空闲多,存储空间小的情况下适合选用 -4. 示例:对 float 和 double 类型都启用有损压缩 -```shell -lossyColumns float|double -``` -5. 配置需重启服务生效,重启如果在 taosd 日志中看到以下内容,表明配置已生效: -```sql - 02/22 10:49:27.607990 00002933 UTL lossyColumns float|double -``` - -### ifAdtFse - -| 属性 | 说明 | -| -------- | -------------------------------- | -| 适用范围 | 服务器端 | -| 含义 | 在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法, FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法 | -| 取值范围 | 0:关闭 1:打开 | -| 缺省值 | 0:关闭 | - -## 3.0 中有效的配置参数列表 - -| # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 | -| --- | :--------------------: | --------------- | ------------------------------- | ------------------ | -| 1 | firstEp | 是 | 是 | | -| 2 | secondEp | 是 | 是 | | -| 3 | fqdn | 是 | 是 | | -| 4 | serverPort | 是 | 是 | | -| 5 | maxShellConns | 是 | 是 | | -| 6 | monitor | 是 | 是 | | -| 7 | monitorFqdn | 否 | 是 | | -| 8 | monitorPort | 否 | 是 | | -| 9 | monitorInterval | 是 | 是 | | -| 10 | queryPolicy | 否 | 是 | | -| 11 | querySmaOptimize | 否 | 是 | | -| 12 | maxNumOfDistinctRes | 是 | 是 | | -| 15 | countAlwaysReturnValue | 是 | 是 | | -| 16 | dataDir | 是 | 是 | | -| 17 | minimalDataDirGB | 是 | 是 | | -| 18 | supportVnodes | 否 | 是 | | -| 19 | tempDir | 是 | 是 | | -| 20 | minimalTmpDirGB | 是 | 是 | | -| 21 | smlChildTableName | 是 | 是 | | -| 22 | smlTagName | 是 | 是 | | -| 23 | smlDataFormat | 否 | 是(从3.0.3.0开始,该配置废弃) | | -| 24 | statusInterval | 是 | 是 | | -| 25 | logDir | 是 | 是 | | -| 26 | minimalLogDirGB | 是 | 是 | | -| 27 | numOfLogLines | 是 | 是 | | -| 28 | asyncLog | 是 | 是 | | -| 29 | logKeepDays | 是 | 是 | | -| 30 | debugFlag | 是 | 是 | | -| 31 | tmrDebugFlag | 是 | 是 | | -| 32 | uDebugFlag | 是 | 是 | | -| 33 | rpcDebugFlag | 是 | 是 | | -| 34 | jniDebugFlag | 是 | 是 | | -| 35 | qDebugFlag | 是 | 是 | | -| 36 | cDebugFlag | 是 | 是 | | -| 37 | dDebugFlag | 是 | 是 | | -| 38 | vDebugFlag | 是 | 是 | | -| 39 | mDebugFlag | 是 | 是 | | -| 40 | wDebugFlag | 是 | 是 | | -| 41 | sDebugFlag | 是 | 是 | | -| 42 | tsdbDebugFlag | 是 | 是 | | -| 43 | tqDebugFlag | 否 | 是 | | -| 44 | fsDebugFlag | 是 | 是 | | -| 45 | udfDebugFlag | 否 | 是 | | -| 46 | smaDebugFlag | 否 | 是 | | -| 47 | idxDebugFlag | 否 | 是 | | -| 48 | tdbDebugFlag | 否 | 是 | | -| 49 | metaDebugFlag | 否 | 是 | | -| 50 | timezone | 是 | 是 | | -| 51 | locale | 是 | 是 | | -| 52 | charset | 是 | 是 | | -| 53 | udf | 是 | 是 | | -| 54 | enableCoreFile | 是 | 是 | | -| 55 | ttlChangeOnWrite | 否 | 是 | | -| 56 | keepTimeOffset | 否 | 是(从3.2.0.0开始,该配置废弃) | | - -## 2.x->3.0 的废弃参数 - -| # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 | -| --- | :---------------------: | --------------- | --------------- | ---------------------------------------------------- | -| 1 | arbitrator | 是 | 否 | 通过 RAFT 协议选主 | -| 2 | numOfThreadsPerCore | 是 | 否 | 有其它参数设置多种线程池的大小 | -| 3 | numOfMnodes | 是 | 否 | 通过 create mnode 命令动态创建 mnode | -| 4 | vnodeBak | 是 | 否 | 3.0 行为未知 | -| 5 | balance | 是 | 否 | 负载均衡功能由 split/merge vgroups 实现 (暂不支持) | -| 6 | balanceInterval | 是 | 否 | 随着 balance 参数失效 | -| 7 | offlineThreshold | 是 | 否 | 3.0 行为未知 | -| 8 | role | 是 | 否 | 由 supportVnode 决定是否能够创建 | -| 9 | dnodeNopLoop | 是 | 否 | 2.6 文档中未找到此参数 | -| 10 | rpcTimer | 是 | 否 | 3.0 行为未知 | -| 11 | rpcMaxTime | 是 | 否 | 3.0 行为未知 | -| 12 | rpcForceTcp | 是 | 否 | 默认为 TCP | -| 13 | tcpConnTimeout | 是 | 否 | 3.0 行为未知 | -| 14 | syncCheckInterval | 是 | 否 | 3.0 行为未知 | -| 15 | maxTmrCtrl | 是 | 否 | 3.0 行为未知 | -| 16 | monitorReplica | 是 | 否 | 由 RAFT 协议管理多副本 | -| 17 | smlTagNullName | 是 | 否 | 3.0 行为未知 | -| 18 | ratioOfQueryCores | 是 | 否 | 由 线程池 相关配置参数决定 | -| 19 | maxStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 20 | maxFirstStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 21 | retryStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 22 | streamCompDelayRatio | 是 | 否 | 3.0 行为未知 | -| 23 | maxVgroupsPerDb | 是 | 否 | 由 create db 的参数 vgroups 指定实际 vgroups 数量 | -| 24 | maxTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 25 | minTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 26 | tableIncStepPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 27 | cache | 是 | 否 | 由 buffer 代替 cache\*blocks | -| 28 | blocks | 是 | 否 | 由 buffer 代替 cache\*blocks | -| 29 | days | 是 | 否 | 由 create db 的参数 duration 取代 | -| 30 | keep | 是 | 否 | 由 create db 的参数 keep 取代 | -| 31 | minRows | 是 | 否 | 由 create db 的参数 minRows 取代 | -| 32 | maxRows | 是 | 否 | 由 create db 的参数 maxRows 取代 | -| 33 | quorum | 是 | 否 | 由 RAFT 协议决定 | -| 34 | comp | 是 | 否 | 由 create db 的参数 comp 取代 | -| 35 | walLevel | 是 | 否 | 由 create db 的参数 wal_level 取代 | -| 36 | fsync | 是 | 否 | 由 create db 的参数 wal_fsync_period 取代 | -| 37 | replica | 是 | 否 | 由 create db 的参数 replica 取代 | -| 38 | partitions | 是 | 否 | 3.0 行为未知 | -| 39 | update | 是 | 否 | 允许更新部分列 | -| 40 | cachelast | 是 | 否 | 由 create db 的参数 cacheModel 取代 | -| 41 | maxSQLLength | 是 | 否 | SQL 上限为 1MB,无需参数控制 | -| 42 | maxWildCardsLength | 是 | 否 | 3.0 行为未知 | -| 43 | maxRegexStringLen | 是 | 否 | 3.0 行为未知 | -| 44 | maxNumOfOrderedRes | 是 | 否 | 3.0 行为未知 | -| 45 | maxConnections | 是 | 否 | 取决于系统配置和系统处理能力,详见后面的 Note | -| 46 | mnodeEqualVnodeNum | 是 | 否 | 3.0 行为未知 | -| 47 | http | 是 | 否 | http 服务由 taosAdapter 提供 | -| 48 | httpEnableRecordSql | 是 | 否 | taosd 不提供 http 服务 | -| 49 | httpMaxThreads | 是 | 否 | taosd 不提供 http 服务 | -| 50 | restfulRowLimit | 是 | 否 | taosd 不提供 http 服务 | -| 51 | httpDbNameMandatory | 是 | 否 | taosd 不提供 http 服务 | -| 52 | httpKeepAlive | 是 | 否 | taosd 不提供 http 服务 | -| 53 | enableRecordSql | 是 | 否 | 3.0 行为未知 | -| 54 | maxBinaryDisplayWidth | 是 | 否 | 3.0 行为未知 | -| 55 | stream | 是 | 否 | 默认启用连续查询 | -| 56 | retrieveBlockingModel | 是 | 否 | 3.0 行为未知 | -| 57 | tsdbMetaCompactRatio | 是 | 否 | 3.0 行为未知 | -| 58 | defaultJSONStrType | 是 | 否 | 3.0 行为未知 | -| 59 | walFlushSize | 是 | 否 | 3.0 行为未知 | -| 60 | flowctrl | 是 | 否 | 3.0 行为未知 | -| 61 | slaveQuery | 是 | 否 | 3.0 行为未知: slave vnode 是否能够处理查询? | -| 62 | adjustMaster | 是 | 否 | 3.0 行为未知 | -| 63 | topicBinaryLen | 是 | 否 | 3.0 行为未知 | -| 64 | telegrafUseFieldNum | 是 | 否 | 3.0 行为未知 | -| 65 | deadLockKillQuery | 是 | 否 | 3.0 行为未知 | -| 66 | clientMerge | 是 | 否 | 3.0 行为未知 | -| 67 | sdbDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 68 | odbcDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 69 | httpDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 70 | monDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 71 | cqDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 72 | shortcutFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 73 | probeSeconds | 是 | 否 | 3.0 行为未知 | -| 74 | probeKillSeconds | 是 | 否 | 3.0 行为未知 | -| 75 | probeInterval | 是 | 否 | 3.0 行为未知 | -| 79 | maxRange | 是 | 否 | 3.0 行为未知 | -| 80 | range | 是 | 否 | 3.0 行为未知 | diff --git a/docs/zh/14-reference/12-directory.md b/docs/zh/14-reference/_12-directory.md similarity index 100% rename from docs/zh/14-reference/12-directory.md rename to docs/zh/14-reference/_12-directory.md diff --git a/docs/zh/14-reference/13-schemaless/13-schemaless.md b/docs/zh/14-reference/_13-schemaless/13-schemaless.md similarity index 100% rename from docs/zh/14-reference/13-schemaless/13-schemaless.md rename to docs/zh/14-reference/_13-schemaless/13-schemaless.md diff --git a/docs/zh/14-reference/13-schemaless/_category_.yml b/docs/zh/14-reference/_13-schemaless/_category_.yml similarity index 100% rename from docs/zh/14-reference/13-schemaless/_category_.yml rename to docs/zh/14-reference/_13-schemaless/_category_.yml diff --git a/docs/zh/25-application/01-car.md b/docs/zh/25-application/01-car.md new file mode 100644 index 0000000000..17e1395f42 --- /dev/null +++ b/docs/zh/25-application/01-car.md @@ -0,0 +1,64 @@ +--- +title: 车联网 +sidebar_label: 车联网 +toc_max_heading_level: 4 +--- + +随着科技的迅猛发展和智能设备的广泛普及,车联网技术已逐渐成为现代交通领域的核心要素。在这样的背景下,选择一个合适的车联网时序数据库显得尤为关键。车联网时序数据库不仅仅是数据存储的解决方案,更是一个集车辆信息交互、深度分析和数据挖掘于一体的综合性平台。它能够实时地采集、处理并存储大量的车辆数据,涵盖车辆定位、行驶速度、燃油消耗、故障诊断等多个维度,从而为车辆的高效管理和性能优化提供坚实的数据支撑。 + +## 车联网面临的挑战 + +在国家政策的有力引导下,车联网行业正迎来前所未有的发展机遇。早在2016年,我国便推出了GB/T 32960标准规范,以推动车联网应用的快速发展。自2017年起,一系列车联网相关政策相继出台,旨在促进网联化、智能化、共享化和电动化的实现。在这一进程中,车联网车与一切技术扮演着举足轻重的角色,其收集的信息中时序数据占据了绝大多数。随着联网汽车数量的持续增长,如何高效地上传、存储和处理海量数据,以及如何有效应对乱序数据的挑战,进行高效的查询和分析,已成为业界亟须解决的关键问题。 + +- 海量数据采集:如今,无论是小型客车还是受监管的货车,普遍配备了T-Box或其他OBD(On-Board Diagnostics,车载自动诊断系统)车载终端设备,用于实时采集车辆的运行参数,并将这些数据及时传输至云端数据中心。以某品牌汽车为例,每辆车每秒可采集140个高频测点数据,每30s采集280个低频测点数据。在日常运营中,80万辆在线车辆每天产生的数据量高达4.5TB,这些数据最终汇入时序数据库,形成了庞大的数据采集点网络。 +- 海量数据存储:鉴于数据采集的规模之大,相应的硬件资源需求自然引起了汽车制造商的高度关注。因此,在选择数据存储方案时,必须考虑高压缩率,最大限度地减少存储空间的占用。同时,应实现冷热数据的自动分离,确保热数据被自动存储到高性能的硬盘上,而冷数据则被转移到较低性能的硬盘上。这样既能保障查询性能不受影响,又能有效降低存储成本,实现资源的合理利用。 +- 支持乱序写入整理:在信号不佳或无信号的区域,数据通常会在本地缓存。一旦网络通信恢复正常,依照GB/T 32960的规定,数据将以交替发送的方式上传至数据中心,确保实时与离线数据的同步传输。在消息分发至不同区域后,消费组的消费顺序也会导致数据的乱序写入。这种乱序写入若频繁发生,将导致大量存储碎片的产生,进而降低时序数据库的存储效率和查询速度。 +- 强大的查询和分析能力:系统应能支持使用标准SQL进行状态、时长、位置等关键指标的统计分析。此外,还应具备轨迹历史回放、双轨合验、预警报警等实用功能,以降低学习和分析的难度。对于更复杂的分析需求,系统须支持UDF,通过编写高级编程语言生成的库文件并加载至集群中,以弥补时序数据库内置函数的局限性。系统应查询操作简便且结果实时性强,以便为业务决策提供有力且及时的数据支持。 + +## TDengine在车联网中的核心价值 + +在面对亿万级别的点位信息时,任何微小的数据处理逻辑错误或冗余都可能导致性能瓶颈。得益于全球社区爱好者的共同努力、超过53万个的装机实例部署,以及在极端条件下的严格验证,TDengine在功能和性能方面均达到顶尖水平。在车联网领域,TDengine的核心价值体现在以下几个方面。 + +- 便于采集:作为物联网的一个分支,车联网的技术特点与之一致。TDengine配备了可视化采集界面,用户无须编写代码即可轻松将Kafka、MQTT等通用消息中间件中 +的数据导入数据库。此外,提供的可视化性能指标看板大大简化了数据接入和管理 +的工作流程。 +- 数据存储:车联网数据具有高度的相关性,例如特定车型的配置信息或同一车辆上不同点位的状态数据。TDengine的设计理念完美契合车联网的需求,采用“一车一表”的模式,简化了数据存储管理的复杂性。结合云原生架构、冷热数据分离、列式存储以及动态扩容(包括横向、纵向扩容和动态添加存储空间)等技术,TDengine在数据存储的性能和成本控制方面表现出色。 +- 查询分析:TDengine作为一个开放且简洁的时序大数据平台,提供了丰富的API,兼容各种分析工具、编程语言和BI系统,如Matlab、R、永洪BI等。TDengine 主要采用SQL,易于学习和使用,支持状态、计数、时间、事件及会话窗口等多种分析模式,并内置了70多个基础算子,足以应对日常的分析需求。对于更专业的算法分析,用户可通过C或Python语言开发UDF,并将其集成到TDengine中。 + +## TDengine在车联网中的应用 + +车联网场景是时序数据应用的典型代表,而TDengine正是处理这类海量时序数据的理想选择。通过整合车载数据,车联网系统能够实现对汽车各个零部件健康状况的监控、用户驾驶行为的追踪、车载系统的安全分析、合规性检查以及车载网络质量的监测。此外,利用TDengine提供的geometry数据类型及其相关函数,车联网系统能够轻松且高效地执行车辆轨迹监管、历史轨迹回放、最新位置定位等关键功能。 + +### TSP 车联网 + +汽车制造商通过车载T-Box终端收集车辆的关键行驶数据,包括行驶速度、行驶方向、电门开度、制动踏板开度、挡位、电机转速以及电池包信息等。这些数据通过MQTT协议汇聚至TDengine进行存储,从而满足车辆历史轨迹的回放需求以及对车辆实时状态的监控。TSP车联网架构如下图所示。 + + +![TSP 车联网架构](./carnet.png) + +TDengine能够无缝地从外部消息队列(如MQTT、Kafka)中采集并过滤数据,用户可通过直观的可视化界面来管理和配置采集任务,实现无须编写代码即可接入外部数据源。此外,TDengine还支持对接入消息的解析、过滤和映射操作,并提供数据采集任务状态的实时监控功能,从而极大地提高数据接入的工作效率。 + +在本案例中,系统采用了“一车一表”的建模策略,确保每张子表中的数据都能按照时间顺序进行追加操作。设备表与表之间保持相对独立,并且数据是连续写入的,这一设计显著提高了数据的写入效率。 +- 海量高频数据采集上报存储:为了应对海量且高频的数据采集与上报需求,系统采用多节点的三副本或双副本集群架构。每个核心节点能够高效管理并存储高达100万张子表。通过分布式部署、构建高可用集群以及实施负载均衡技术,系统确保了数据采集存储在性能、可用性和可靠性方面的卓越表现。 +- 采用多级存储方式:系统支持冷热数据分离的策略,将热数据存储于高性能的硬盘上,而冷数据则可根据配置迁移至S3对象存储服务中,实现存储方式的灵活性。鉴于数据量的庞大,多级存储不仅满足了日常业务需求,还有效降低了存储成本。通过独特的数据存储结构设计,实现了行转列和连续存储,无损压缩率轻松达到10%以内,极大地节约了数据存储空间。 +- 预统计和缓存:在数据写入存储空间的过程中,系统已经计算并附带了max、min、avg、count等预统计结果。这些预计算结果为大多数统计分析提供了基础,使得在数据量庞大时,能够通过统计函数迅速筛选出所需信息。在处理海量数据的并发写入场景时,系统展现出高效的统计报表生成能力和卓越的SQL查询效率。此外,系统内置的实时缓存功能能够实现毫秒级的实时数据反馈。 +- 在线异步方式数据整理:此过程不会干扰正常的存储和查询服务,而是对乱序数据和因数据删除产生的存储碎片进行整理,有效释放存储空间。 +- 系统部署满足分布式、高可用以及负载均衡的需求,其性能、可靠性和稳定性已经过充分验证。 +- 极简大数据平台:与传统大数据平台相比,系统将消息队列、流计算、实时缓存、ETL工具以及数据库本体集成于一体,构建了极为简洁的架构,同时增强了实时性,大幅减少了验证和维护过程中的工作量。 + +### 物流车联网 + +物流车辆运营商借助车辆的轨迹监管、异常预警以及历史轨迹回放功能,实现对运营车辆的在线监控、精准轨迹追踪、深入大数据分析及可视化应用等多方面目标。 + +在这一业务场景中,系统数据建模遵循“一车一表”的原则进行设计。GIS (Geographic Information System,地理信息系统)网关负责收集并汇聚数万台车辆上报的车辆定位和行驶数据。随后,下游服务解析这些报文并将数据推送至消息队列。通过TDengine的数据接入组件,数据经过加载、过滤和转换等一系列处理步骤后,最终存储于TDengine中。这为下游应用程序提供了实时的车辆位置监控和历史轨迹回放等查询分析服务。物流车联网系统的架构如下图所示: + +![物流车联网系统架构](./distribution.png) + +方案特点如下。 +- 高性能:该项目服务于一万辆车,数据量呈现快速增长态势,日均写入记录高达约10亿条。项目对聚合查询的高效性和存储压缩性能进行了严格的验证,无损压缩率可达4%。这证明了TDengine在处理大规模数据时的卓越性能。 +- 乱序治理:尽管消息队列的使用难以避免乱序问题的出现,尤其是在离线数据补传的场景中,乱序数据往往表现为时间戳早于当前车辆存储记录的时间戳。这种乱序写入会导致大量存储碎片的产生,严重时会影响数据库的性能。TDengine巧妙地解决了这一行业难题,支持在线整理乱序写入,确保数据库性能不受影响。同时,对于异常数据段的删除,也可以通过在线整理实现真正的数据存储空间释放,而不仅仅是索引屏蔽。 +- 数据应用:鉴于车辆运营涉及食品安全的特殊性,实时监控当前车辆位置信息显 +得尤为重要。TDengine 具备缓存实时数据的功能,无论数据库中已存储多少数据, +仍能保持稳定的性能,毫秒级响应最新数据请求,充分发挥时序数据库的实时特 +性。业务中还需要进行历史轨迹回放、行驶里程分析、时间分段分析等多项操作, +TDengine 的强大性能和多功能性为业务分析提供了无限可能。 \ No newline at end of file diff --git a/docs/zh/25-application/02-new-energy.md b/docs/zh/25-application/02-new-energy.md new file mode 100644 index 0000000000..133e05b355 --- /dev/null +++ b/docs/zh/25-application/02-new-energy.md @@ -0,0 +1,87 @@ +--- +title: 新能源 +sidebar_label: 新能源 +toc_max_heading_level: 4 +--- + +在当前可再生能源迅速发展的浪潮中,分布式光伏和可再生能源的装机容量已经达到相当可观的规模。尽管新能源的发展得到政策的鼎力扶持,但其并网后对电网的运行调度、供电可靠性以及系统的安全稳定带来诸多新挑战。 + +分布式光伏,即分布式光伏发电系统,是指将光伏电池板安装在城市的建筑物屋顶或墙壁上,甚至农田、山坡等非建筑用地上,利用采集到的太阳能为城市供电的一种绿色能源解决方案。其显著特点是电力产生地与用电地重合,可以直接向用户提供电力,或者通过配电变压器并入电网。这种能源系统不仅环保,而且高效,能有效降低长距离输电的损耗,减少能源使用成本。分布式光伏电站主要由光伏电池板、组串式逆变器、配电设备和监控系统4部分组成。光伏电池板负责将太阳能转换为直流电,组串式逆变器进一步将直流电转换为交流电,供用户使用或并入电网。电力公司普遍采用HPLC (High-speed Power Line Communication,高速电力线通信)方案对分布式光伏接入的电能表进行数据采集,以实现1分钟、15分钟级别的运行数据采集能力。 + +储能系统以其独特的能力,能够平滑新能源输出的不稳定性,实现削峰填谷,从而有望显著降低微电网的运行成本。更为重要的是,从长远角度考虑,引入储能系统有助于减轻对主电网的依赖,进一步优化整体的能源结构。 + +新能源的波动性无疑加剧了电网供电的不确定性,这使得储能系统成为确保电网稳定性和可靠性的关键。针对这方面,《2030年前碳达峰行动方案》明确强调了储能系统的重要性,并支持分布式新能源与储能系统的融合发展,旨在加速储能技术的示范应用和推广普及。 + +## 新能源面临的挑战 + +分布式光伏在绿色环保的电力生产方面做出了显著贡献,然而其并入电网后,对电网调度提出了新的挑战。这些挑战包括如何高效地将运行数据接入电网调度中心、如何迅速将数据分发至各个地区、如何进行有效的数据分析等。随着分布式光伏的大规模推广,电网运营商必须妥善解决这些问题,以确保电网的稳定性和安全性得以维持。 + +储能系统的核心组件是电芯,对其实时工作参数(如电流、电压、温度、内阻)的监控对于保障储能系统的安全和可靠运行至关重要。如何有效地存储和分析这些海量的测点和数据,已成为储能领域不得不正视的技术难题。这些难题主要体现在如下几个方面。 +- 测点量大:分布式光伏组件众多,大型储能系统中电芯数量庞大,需要监测的测点数从数十万到数千万不等。加之较高的采集频率,每天产生的海量监测数据需要进行长期持久化存储。 +- 数据接入难:电网调度中心须实时监控分布式光伏电站和储能系统的运行状况,但由于分布式光伏电站目前主要通过配网侧接入电网,数据接入过程面临挑战。 +另外,由于营销系统与调度中心的信息化水平存在差异,数据接入过程中存在客观难题:数据提取规则复杂,测点数量庞大,传统的数据采集方案资源消耗大。 +- 数据分发难:分布式光伏电站的运行数据一旦接入省级调度中心,就需要迅速分发至各地市的生产区以驱动后续业务。如何实现快速且高效的数据分发,是客户 +需要解决的一个棘手问题。 +- 聚合分析难:分布式光伏电站的运行数据须根据电站在电网拓扑中的具体隶属关系(如电站隶属于某台配电变压器、馈线、主网变压器)进行多维度的聚合分析。现有技术方案在提供高效聚合分析手段方面存在不足,如性能低下、耗时过长等问题尤为突出。 + +## TDengine在新能源中的核心价值 + +在新能源领域,特别是分布式光伏电站和储能系统的复杂任务与数据处理需求面前,TDengine的时序数据库技术扮演了不可或缺的角色。TDengine的核心优势体现在以下几个方面。 + +- 支持海量测点:TDengine能够支持高达10亿个时间线,充分满足分布式光伏电站和储能系统的数据处理需求。 +- 高性能:面对千万级测点的分钟级数据采集场景,调度业务对时序数据库的写入性能和低延迟有着严苛的要求。TDengine凭借“一个数据采集点一张表”的创新设计理念,实现了卓越的写入性能,完全契合业务需求。 +- 最新状态数据快速查询:在千万级测点数据写入后,调度业务需要时序数据库能够迅速查询各设备的最新状态数据,以驱动后续业务逻辑。TDengine通过超级表和内置的高速读缓存设计,使用户能够高效查询光伏设备和储能电芯的最新运行数据,使运维人员能够实时获取并监控设备状态,从而提高运维效率。 +- 数据订阅与分发:针对需要实时数据分发的业务场景,TDengine内置的消息队列功能从机制上解决了大量数据即时分发的难题,简化了整个系统架构的复 +杂性。 +- 开放的生态:TDengine易于与其他系统集成,兼容多种大数据框架,支持数据的整合与分析,为开发者提供了一个灵活的生态平台。 + +## TDengine 在新能源中的应用 + +### 营销侧分布式光伏电站运行数据接入 + +分布式光伏电站的运行数据通常须从外部营销系统接入,而该营销系统所提供的数据接口采用的是Kafka,如下图所示: + +![从营销系统接入 TDengine](./energy-kafka.png) + +针对外部数据源的接入场景,TDengine Enterprise提供了专业的taosX数据接入组件。用户无须编写任何代码,只须通过配置参数即可迅速接入营销侧Kafka消息队列中的分布式光伏电站采集数据,实现提取解析、过滤、数据映射等操作,并将处理后的数据写入TDengine。这种方法不再依赖第三方ETL工具,如下图所示: + +![TDengine外部数据源接入流程](./energy-data-in.png) + +taosX是一个高度灵活的数据接入工具,能够适应多样化的数据源格式。它配备了全面的过滤选项和丰富的数据映射功能,这些特性大幅缩短了从外部系统收集并整合数据的开发周期。在维持低资源消耗的同时,taosX保证了高效的数据接入能力。 + +与市面上常见的开源ETL工具相比,taosX在接入Kafka数据时能够显著减少服务器CPU资源的占用。这不仅意味着企业能够在更短的时间内完成数据接入任务,还能有效降低硬件成本,为企业的发展提供强有力的支持。 + +### 数据即时分发至各地市 + +针对汇总至省级调度中心的分布式光伏电站运行数据,用户须将这些数据及时分发至各地市的调度中心,以便推动下游业务的顺利进行。 + +利用TDengine内置的结构化消息队列功能,用户可以迅速构建数据分发子系统。通过订阅省级调度中心TDengine集群中的分布式光伏电站瞬时功率数据,并根据各地市进行分类,实时将数据分发至对应地市的TDengine。各地市调度中心根据收到的数据,进一步驱动后续业务,如本地电网负载调控等。分布式光伏电站运行数据的分发架构如下图所示: + +![分布式光伏电站运行数据的分发架构](./energy-distribution.png) + +### 分类聚合计算瞬时发电功率 + +分布式光伏电站通过配电变压器并入配电网,并逐级向上汇聚至配网的10kV线端和110kV主网变压器。各级配电变压器、10kV线端、馈线以及110kV主网变压器所汇集的分布式光伏电站瞬时发电功率,对电网的安全稳定运行具有决定性的影响。 + +在一个省份中,分布式光伏电站和配电变压器的数量庞大,可达百万级别。每个分布式光伏电站和配电变压器通常设有8至10个测点,涵盖三相电流电压、功率、功率因数、示值等指标,总测点数往往超过千万个。在这种大规模的测点环境下,实现快速聚合计算成为一个关键挑战。 + +TDengine的标签设计允许用户从超级表中迅速分类和检索数据,这一点对于基于分布式光伏电站产生的大量时序数据进行快速聚合计算尤为重要。在TDengine中,通常会分别为分布式光伏电站发电功率和配电变压器的瞬时功率创建超级表,每个分布式光伏电站和配电变压器分别对应一张子表。通过TDengine的静态标签,可以存储分布式光伏电站发电功率的相关分类信息,如地区、所属配电变压器、所属馈线、所属10kV单端线端、所属110kV主网变压器等。 + +用户可根据多样化的标签,如地区、所属配电变压器、所属馈线、所属主网变压器等,对分布式光伏电站执行指定条件的聚合查询,实现快速求解。例如,用户可以迅速查询特定地区内所有配电变压器的下辖分布式光伏电站瞬时发电功率,或根据业务需求,针对不同级别的电网变电站(220kV、110kV、35kV、10kV)进行下辖分布式光伏电站瞬时功率的条件聚合查询。这为电网调度和设备故障判断提供了高效的数据支持手段。此类条件聚合查询的结果集可能包含数百至数十万条记录。 + +在TDengine中,用户可以基于标签进行聚合分析,无须编写代码进行表关联和数据处理,仅须通过SQL查询超级表即可直接获得结果,性能表现卓越,通常能在几秒内返回查询结果。示例SQL如下。 +```sql +select sum(val) from dpv_power_1m where ts > now-1m group by dtr; +``` + +借助TDengine的高效聚合特性,用户可以高效、及时地获得分布式光伏电站实时运行状态,为运行决策提供可靠的数据支持。 + +### 实时数据监测 + +在某储能项目中,TDengine被应用于实时监控电池的充放电过程,以保障电池的安全运行。所有电芯的充放电数据都被精确记录,得益于TDengine的强大分析能力,用户显著提高了数据处理和分析的效率。 + +### 智慧运维系统 + +在某储能智慧运维系统中,用户原有的解决方案受到站端系统在内存、CPU以及读写性能等硬件资源上的限制,这导致项目进度一再推迟。TDengine凭借卓越的架构设计和工程实现,以较低的资源消耗完美满足了项目需求,解决了客户的痛点问题,并迅速支持业务系统的顺利部署。 + +TDengine的加入为储能设备注入了信息感知、控制协调以及远程运维的能力,确保了电站和设备运行的安全性与可靠性。 \ No newline at end of file diff --git a/docs/zh/25-application/03-oil.md b/docs/zh/25-application/03-oil.md new file mode 100644 index 0000000000..a78b0963ec --- /dev/null +++ b/docs/zh/25-application/03-oil.md @@ -0,0 +1,80 @@ +--- +title: 智慧油田 +sidebar_label: 智慧油田 +toc_max_heading_level: 4 +--- + +智慧油田,亦称为数字油田或智能油田,是一种采用尖端信息技术与先进装备的现代油田开发模式。该模式通过实时更新油气田层析图及动态生产数据,显著提高了油气田的开发效率与经济价值。 + +信息技术在此领域发挥着至关重要的作用,涵盖了数据采集、传输、分析以及处理等多个环节。借助这些技术,客户能够随时随地访问到最新、最准确的油田信息。在硬件设施方面,广泛部署的传感器和控制设备为油田生产的自动化与智能化提供了坚实的技术支撑。 + +智慧油田的核心特征体现在以下几个方面。 +- 数据驱动:在智慧油田的管理中,决策的核心依据是源自现场的实际数据,而非传统依赖的人为经验和直觉。这种基于数据的决策方式显著提升了决策的精准度与可信度。 +- 实时监控:得益于实时的数据采集与高效传输,客户能够全天候掌握油田的运营状况。这有助于迅速发现问题并采取措施,有效预防潜在损失,从而节省大量成本和资源。 +- 智慧决策:将大数据分析技术融入决策流程,使得客户能够更深层次地理解油田的运作机制,并进行准确预测。基于这些数据和洞察,客户能够制定出更为科学合理的决策方案。 +- 自动化操作:借助先进的自动化设备,客户可以将许多重复性高、劳动强度大乃至存在安全风险的任务交由机器执行。这不仅大幅提高了工作效率,降低了运营成本,还有效减少了意外事故的发生概率,保障了员工的安全和企业的稳定运营。 + +## 智慧油田面临的挑战 + +智慧油田的建设之旅是一场既复杂又漫长的征途,它横跨勘探、开发、生产等多个关键环节。随着技术的不断进步和业务的日益拓展,油田运营面临着效率提高、成本控制以及数据安全方面的全新挑战。 + +面对油田业务产生的庞大数据集,这些数据涵盖了钻井、录井、测井及生产开发等多个方面,油田信息化系统必须具备卓越的数据处理能力。这不仅要求系统能够确保运营的顺畅进行,还须借助先进的数据压缩技术,有效节约存储空间,进而降低硬件投资成本。 + +智慧油田系统还应设计为能够基于业务需求进行灵活扩展。系统须能够随着业务增长和数据量的上升,无缝地整合新的存储和计算资源,确保服务的连续性和性能的稳定性。此外,系统的用户友好性同样不容忽视,通过简洁直观的操作界面和标准化操作流程,减少员工的学习曲线,从而提高整体工作效率。 + +对于高价值的油田数据,安全保障措施至关重要。这包括实施持续的数据备份、监控系统健康状况、制订故障恢复计划,以及强化数据的加密和访问管理措施,以充分保障油田数据的安全性和可靠性。 + +为了满足智慧油田项目在数据处理、系统扩展性、用户体验以及数据安全等方面的需求,我们必须采取全面而审慎的态度。选择合适的大规模时序数据管理解决方案,例如TDengine,将为油田行业提供坚实的科技支撑,推动其向更高水平发展。 + +## TDengine在智慧油田中的应用 + +在一项致力于提升大型油田生产管理水平的技术方案中,客户设定了实现多个关键领域技术集成的目标。这些领域包括但不限于如下这些 +- 自动化采集与控制:在生产现场构建先进的自动化系统,以实现数据的实时采集和精确控制,提升生产过程的自动化水平。 +- 生产视频系统:整合高效的视频监控系统,对生产过程进行全面监控,确保作业安全,并为管理层提供实时、直观的决策支持。 +- 工业物联网:运用物联网技术,将各种传感器和设备无缝连接,实现数据的远程采集与分析,提高油田运营的透明度和智能化程度。 +- 生产数据服务:构建强大的数据服务平台,提供及时、准确的数据支持,为生产决策和运营优化提供有力工具。 +- 智能化生产管控应用:研发智能化的生产管控应用,利用大数据分析和人工智能技术,提高生产效率,优化资源配置,加强生产管理。 +- 信息化采集标准建设:制定统一的信息化采集标准和规范,确保数据的一致性、准确性和可管理性,为油田的数字化和智能化转型奠定坚实基础。 + +以往的技术解决方案中,客户普遍采用常规的实时数据库来搜集现场数据。然而,这些传统软件在数据分析功能上显得力不从心。鉴于此,用户不得不将数据迁移到以Oracle为代表的关系型数据库中,以期利用这些数据库作为数据汇聚与分析的核心平台。 + +但随着油田数据量的激增,客户遭遇了两大核心挑战:一是数据采集量的快速增长,二是数据采集频率的显著提高。在这种背景下,传统关系型数据库在数据处理上开始显现出一系列问题和瓶颈。 + +- 随着数据库中存储的数据量不断攀升,无论是数据写入还是查询操作的效率都遭受严重影响,尤其是在执行复杂查询和大数据集聚合操作时,性能下滑尤为显著。 +- 数据压缩效率低下,导致数据库占用了巨量的存储空间,这不仅造成了资源的浪费,也给数据管理和维护带来了额外的负担。 +- 当面临多用户或应用程序并发访问时,数据库常常会遇到并发控制和锁的竞争问题,这不仅影响系统性能,还可能引发数据一致性问题。 +- 数据的分区和归档操作变得异常复杂,一旦系统出现故障,恢复数据所需的时间极为漫长,这对业务连续性构成了严重威胁。 +- 数据协同效率低下,难以实现秒级的数据同步,这对于需要快速响应的业务场景来说是一个巨大的限制。 + +在这样的项目背景下,TDengine凭借作为时序数据库的独特优势,展现出强大的竞争力。TDengine以高效的数据处理速度、卓越的数据压缩率、直观的系统易用性以及出色的可扩展性,有效地支持了智慧油田项目在数据管理和分析方面的需求。此外,TDengine还覆盖了数据生命周期的全管理流程,并积极应对日益严峻的数据安全挑战,确保了大型项目在技术上的顺利优化和升级。 + +TDengine的“一个数据采集点一张表”与“超级表”的创新设计理念,极大地提高了时序数据的写入、查询和存储效率。如下图所示,当客户采用TDengine后,他们可以根据不同专业领域的多样化数据需求,创建相应的超级表。以油井为例,客户首先须细致梳理业务所需的数据项及其采集频率,随后为每一口油井建立一张独立的表,并为这些表附加相应的静态标签,如采油厂名称、所属业务部门等。这样的设计不仅确保了数据的精细化管理和高效检索,还极大地简化了数据的组织和维护工作。 + +![TDengine 在智慧油田中的应用](./oil-1.png) + +在将Oracle全面迁移至TDengine之后,该项目的优化效果显著,具体体现在以下几个方面。 +- 数据写入性能显著提升,同时硬件资源消耗得以降低,实现了更高的资源利用率。 +- 集群支持在线水平扩展,使得未来面对扩容需求时能够轻松应对,保证了系统的可扩展性和前瞻性。 +- 灵活定义数据的生命周期,简化了过期数据的管理流程,提高了数据管理的效率和便捷性。 +- 达到每秒500万测点的同步速率,这一性能指标满足了用户在边云协同场景下的高实时性需求,为数据的高效流动和利用提供了有力保障。 + +如果说前3点是TDengine固有特性的体现,那么第4点无疑是其核心价值所在。为了满足人工智能研究、数据挖掘、设备预测性维护等多方面的数据需求,客户经常需要将各个厂级的油田实时数据集中汇聚至公司层面,然后再进一步将公司数据整合至集团或相应的业务板块。如下图所示,这一过程对数据的实时性和同步性提出了极高要求,TDengine的出色表现确保了这一关键环节的顺畅运行。 + +![智慧油田边云同步](./oil-2.png) + +在传统业务模式中,由于需要定义众多复杂的数据接口,导致业务开发效率低下,且数据传输频率受限,难以满足对原始数据和原始频率进行同步的需求。在这一关键节点上,客户可以充分利用TDengine的边云协同功能,实现数据的实时高效同步。 + +边云协同允许将多个分散在不同地点的TDengine服务中的全量历史数据以及新产生的数据实时同步至云端TDengine。作为TDengine套件的重要组成部分,taosX工具简化了这一过程。用户只须在数据接收端部署taosX,并通过一行简单的命令,即可轻松实现实时数据同步、历史数据迁移,或是两者的混合处理方案。例如,同步某台服务器的db1 的历史数据以及实时数据到本地的db2数据库仅需要执行如下一条命令。 +```shell +taosxrun-f'taos://192.168.1.101:6030/db1?mode=all'-t'taos://localhost:6030/db2'-v +``` + +此外,taosX提供了一种基于数据订阅的实时数据同步方法,它按照事件到达的顺序来处理数据。这种方法确保了无论是实时数据还是历史数据的写入,都能够实时同步到目标集群,并且不会遗漏任何补录的历史数据。 + +通过实施这一方案,多个TDengine服务得以通过taosX跨省份实时同步数据至云端总部集群。迄今为止,在该项目中,TDengine总部集群存储的数据量已达到36TB,总数据条目超过1034亿条,压缩率降至10%以内,这一成就令人瞩目。 + +边云协同功能的广泛采用充分验证了TDengine在处理大规模、高频工业数据方面的卓越实力。其灵活的架构设计和优化的存储机制不仅满足了工业物联网环境对实时数据处理的高要求,而且有效降低了存储成本。同时,TDengine的水平扩展性、实时分析支持、边缘计算集成以及强大的数据安全保护功能,为工业物联网的智能化发展奠定了坚实的技术基础。这不仅确保了数据处理的高效性和安全性,还简化了维护流程,相较于传统关系型数据库,展现了更高的成本效益。TDengine的这些优势为工业物联网的持续进步和发展提供了强有力的支持和保障。 + +随着项目的深入推进,TDengine的数据抽稀功能,作为处理和管理时序数据的一种高效策略,在与Kudu为核心的数据中台相结合时,展现出非凡的能力。数据抽稀通过精心挑选具有代表性的数据点,有效减少了数据的存储量,同时确保了数据的关键特征和趋势得以完整保留。这种方法特别适合于那些需要长期保存数据但又不必要保留所有细节的应用场景。例如,在监控系统中,随着时间的积累,只须保存关键时间节点的数据,而不是每个瞬间的数据。 + +因此,TDengine成为构建数据中台的理想选择,尤其是对于那些需要高效处理大量时序数据的中台环境。通过将TDengine集成到数据中台中,企业能够进一步优化其数据存储、查询和管理流程,从而提高数据平台的功能性和效率。TDengine的这一特性不仅提高了数据处理的速度和效率,还为企业提供了更加灵活和经济的数据管理解决方案。 \ No newline at end of file diff --git a/docs/zh/25-application/04-manufacture.md b/docs/zh/25-application/04-manufacture.md new file mode 100644 index 0000000000..c1983d67c1 --- /dev/null +++ b/docs/zh/25-application/04-manufacture.md @@ -0,0 +1,64 @@ +--- +title: 智能制造 +sidebar_label: 智能制造 +toc_max_heading_level: 4 +--- + +智能制造与数据库技术的深度融合,已成为现代工业技术进步的一个重要里程碑。随着信息技术的飞速发展,智能制造已经成为推动工业转型升级的关键动力。在这一进程中,数据库技术扮演着不可或缺的角色,它不仅承载着海量的生产数据,还为智能制造提供了强大的数据支持和服务。 + +特别是随着大数据、云计算等前沿技术的崛起,TDengine凭借灵活多变的数据模型和卓越的数据处理能力,在智能制造领域大放异彩。TDengine能够高效地管理和分析制造过程中的各类数据,从生产线的实时监控到产品质量的精细管理,再到供应链的优化协调,它都能提供精准可靠的数据支持。 + +## 智能制造面临的挑战 + +依照传统的IEC 62264-1层次模型,工业制造领域被划分为5个层级—现场设备层、现场控制层、过程监控层、生产管理层及企业资源层。这一模型清晰地描绘了从生产现场的实时操作到企业管理层面的战略规划,每一层级的跃迁都伴随着数据量的急剧增长和需求的变化,如下图所示。这种层级划分不仅反映了工业制造过程中信息流动的复杂性,也揭示了随着生产规模的扩大和自动程度的提高,对数据处理能力和效率的要求也在不断提升。 + +![IEC 62264-1 5 层架构模型](./manufacture-1.png) + +随着工业数字化的巨浪席卷而来,我们见证了数据采集量的爆炸式增长和分析需求的日益复杂化,随之而来的问题和挑战也愈发凸显。 +- 海量设备数据采集:在过去的十余年里,制造业的数字化进程取得了显著进展。工厂的数据采集点从传统的数千个激增至数十万甚至数百万个。面对如此庞大的 +数据采集需求,传统的实时数据库已显得力不从心。 +- 动态扩容:随着数据的逐步接入,初期的硬件配置往往较为有限。随着业务量的增加和数据量的上升,硬件资源必须迅速扩展以满足业务的正常运行。然而,一旦系统上线运行,通常不允许进行停机扩容,这就要求系统在设计时就要考虑到未来的扩展性。 +- 数据关联与多维分析:传统工业实时数据库通常只包含几个固定的字段,如变量名、变量值、质量戳和时间戳,缺乏信息间的关联性,这使得复杂的多维分析变 +得难以执行。 +- 截面查询与插值查询:为了满足报表和其他统计需求,系统需要支持历史截面查询以及按指定时间间隔进行的线性插值查询。 +- 第三方系统数据库对接:除了设备数据以外,还须采集来自各个生产系统的数据,这些系统通常位于过程监控层或生产管理层。这就要求系统能够实时采集数据、迁移历史数据,并在网络断开时能够断线续传。除了API以外,常见的对接方式还包括数据库对接,例如,与LIMIS对接,采集其关系型数据库中存储的时序数据,或与第三方生产数据库(如AVEVA PI System或Wonderware系统)对接,获取实时、历史和报警数据。 +- 与SCADA(Supervisory Control and Data Acquisition,监控控制与数据采集)系统对接:SCADA系统作为过程监控层的核心,汇集了站内和厂区的所有生产数据,并提供了直观易用的开发、运行和管理界面。然而,其自带的传统实时数据库在分析能力和高密度点位容量上存在限制,通常仅支持约1万个点位。因此,将SCADA系统与性能更优越的数据库相结合,充分发挥双方的优势,通过面向操作技术层的模块化组态开发,为工业控制系统注入新的活力,已成为工业数字化发展的重要方向。 + +## TDengine在智能制造中的核心价值 + +智能制造领域涵盖众多类型的数据设备、系统以及复杂的数据分析方法。TDengine 不仅巧妙解决了数据接入和存储的挑战,更通过强大的数据分析功能,为黄金批次、设备综合效率(Overall Equipment Effectiveness,OEE)、设备预防性维护、统计过程控制(Statistical Process Control,SPC)等关键分析系统提供了卓越的数据统计服务。这不仅显著提高了生产效率和产品品质,还有效降低了生产成本。 + +- 广泛兼容各种设备和系统:TDengine配备了可视化配置的采集器,能够轻松对接SQL Server、MySQL、Oracle、AVEVA PI System、AVEVA Historian、InfluxDB、OpenTSDB、ClickHouse等多种系统,支持实时数据采集、历史数据迁移以及断线续传等功能。通过与诸如Kepware或KingIOServer这样的强大第三方采集平台对接,TDengine能够应对各种工业互联网协议,实现海量生产设备数据的接入。 +- 高效的集群管理:与传统实时数据库相比,TDengine采用了基于云原生技术的先进架构,能够轻松实现动态扩容。TDengine集群采用Raft强一致性协议,确保生产数据对外查询结果的一致性。集群的运维管理简便,内部自动完成数据分区和数据分片,实现了分布式、高可用性和负载均衡的集群环境。 +- 设备物模型:TDengine秉承“一台设备一张表”的设计策略,构建了以设备对象为核心的变量关系模型,为相关分析提供了坚实的基础。 +- 先进的时序分析:TDengine支持时序领域的截面查询、步进查询、线性插值查询等多种查询方式,并提供了窗口查询功能,使得设备状态时长统计、连续过载报警等时序分析变得简单易行。 + +## TDengine在智能制造中的应用 + +作为新一代时序大数据平台的杰出代表,TDengine针对工业场景中的种种挑战,凭借独特的设计理念和卓越的性能,为智能制造领域注入了强大的动力。接下来以某烟厂的实际应用案例为例进行阐述。 + +在该项目中,TDengine集群为工厂内的各类业务提供了坚实的时序数据服务。无论是看板展示还是预警系统等对实时数据要求极高的业务场景,TDengine都能够提供低延迟、高质量的数据响应。自系统上线以来,已稳定运行超过两年,成功存储超过2万亿条数据,且查询最新数据的延迟控制在毫秒级,完全达到项目立项的预期要求。该项目的亮点设计如下 + +- 高效采集:烟草项目初期规模有限,全厂测点数不足10万。数据采集网关将部分测点数据写入OPC(OLE for Process Control,用于过程控制的OLE)服务器,并通过OPC协议接入TDengine;另一部分测点数据则写入Kafka,进而接入TDengine。客户无须开发OPC或Kafka接口应用程序,即可实现数据的高效接入。对于采用关系型数据库如LIMIS的场景,TDengine通过可视化配置SQL Server采集器,实现了数据的同步更新、历史数据迁移、断线续传以及故障诊断等功能,无须编写代码,大幅降低了开发和运维成本。在其兄弟单位中,部分生产系统使用Wonderware数据库(现AVEVA Historian),TDengine通过建立AVEVA Historian采集器,同样实现了零代码可视化配置,轻松完成实时数据接入、历史数据迁移及断线续传等功能。相较于初次定制化开发长达3个月的交付周期,TDengine采集器的部署仅需要十几分钟,且具有更强的可靠性和灵活性。 +- 动态扩容和负载再均衡:为应对未来业务的增长,TDengine支持在不停止服务的前提下进行动态的纵向和水平扩容。在单台计算机资源充足的场景下,TDengine 可通过拆分虚拟节点服务,充分利用计算机的额外CPU资源来提高数据库性能。而在资源不足的情况下,只须增加物理节点,TDengine集群便能根据需求进行自动负载均衡。 +- 支持建立大宽表:TDengine的这一设计满足了数据关联和多维分析的需求,解决了传统工业实时数据库固定格式数据存储的限制。通过超级表的静态标签设计, +用户可以便捷地进行多维度数据分析。 +- 支持丰富的对外接口:作为数据中心,TDengine可对接第三方可视化界面(如看板)、MES、预警报警、水分预测、零配件需求预测、SPC、故障分析、产能分析、能耗分析、预防性维护等系统,如下图所示: + +![TDengine支持丰富的对外接口](./manufacture-2.png) + +- TDengine与SCADA系统的融合:生产调度中心常采用SCADA系统进行数据采集、监视和控制。SCADA系统通过TDengine的ODBC接口,将实时和历史数据、设备报警、操作记录、登录信息以及系统事件等数据存储到TDengine中。与SCADA系统自带的历史库相比,客户在查询曲线、报表等历史数据时耗时更短、响应更快、灵活性更强,这不仅降低了对SCADA系统的压力,还提高了整个系统的效率和稳定性。 + +此外,TDengine还支持云边系统部署,如下图所示: + +![TDengine支持边云协同系统部署](./manufacture-3.png) + +在工厂侧部署TDengine,不仅为该烟厂提供数据存储、查询和分析服务,还能通过高效的数据同步工具,实现工厂数据实时同步至上一级或集团中心。TDengine的量化裁剪功能使其能够适应资源有限的计算机或边缘盒子环境,满足不同规模部署的需求。TDengine的同步特性如下。 + +- 统计意义的降采样同步:TDengine利用流计算技术,实现了具有统计意义的降采样数据同步。通过这种方式,可以在不损失数据精度的前提下,对数据进行降采样处理,确保即使在数据时间颗粒度增大的情况下,也能保持数据的准确性。流计算的使用方式简便,无须复杂配置,客户只须根据自己的需求编写SQL即可实现。 +- 订阅式传输:TDengine采用了类似Kafka的消息订阅方式进行数据同步,相较于传统的周期性同步和普通订阅访问,这种方式实现了负载隔离和流量削峰,提高了同步的稳定性和效率。消息订阅机制遵循至少一次消费原则,确保在网络断线故障恢复后,能够从断点处继续消费数据,或者从头开始消费,以保证消费者能够接收到完整的生产数据。 +- 操作行为同步:TDengine能够将操作行为同步到中心端,确保设备故障或人为对边缘侧数据的修改和删除操作能够实时反映到中心侧,维护了数据的一致性。 +- 数据传输压缩:在数据传输过程中,TDengine实现了高达20%的数据压缩率,结合流计算的降采样同步,显著降低了同步过程对带宽的占用,提高了数据传输 +效率。 +- 多种同步方式:TDengine支持多对一、一对多以及多对多的数据同步模式,满足不同场景下的数据同步需求。 +- 支持双活:数据中心侧可实现异地灾备。边缘侧的TDengine或第三方客户端能够根据集团中心侧的TDengine状态进行智能连接。若主TDengine集群发生故障,无法对外提供服务,异地备用的TDengine集群将立即激活,接管所有客户端的访问连接,包括写入和查询功能。一旦主TDengine集群恢复正常,备用集群会将历史缓存和实时数据同步回主集群,整个过程对客户端透明,无须人工干预。 \ No newline at end of file diff --git a/docs/zh/25-application/05-finance.md b/docs/zh/25-application/05-finance.md new file mode 100644 index 0000000000..a4f4c30e22 --- /dev/null +++ b/docs/zh/25-application/05-finance.md @@ -0,0 +1,84 @@ +--- +title: 金融 +sidebar_label: 金融 +toc_max_heading_level: 4 +--- + +金融行业正处于数据处理能力革新的关键时期。随着市场数据量的爆炸式增长和复杂性的日益加深,金融机构面临着寻找能够高效处理大规模、高频次以及多样化时序数据的大数据处理系统的迫切需求。这一选择将成为金融机构提高数据处理效率、优化交易响应时间、提高客户满意度以及维持竞争优势的决定性因素。 + +在金融领域,行情数据的处理尤为复杂,不仅数据量大,而且具有标准化的数据格式、长期的存储需求以及高度分散的子表管理要求,这些特点共同构成了数据处理领域的一大难题。具体挑战如下。 + +- 数据量庞大:金融市场的数据量达到TB级别,这为数据的存储和管理带来巨大的挑战。金融机构需要确保有足够的能力来处理和存储这些数据,同时保证系统的稳定性和可扩展性。 +- 标的数量众多:金融市场中资产和衍生品的种类繁多,这意味着行情中心需要管理数十万至数千万个不同的标的。这种多样性和数量级的增长要求系统必须具备高度的灵活性和高效的管理能力。 +- 存储期限长:金融数据的敏感性要求这些数据必须被长期保存,通常存储期限为5至10年,有些关键数据甚至需要保存超过30年。这要求金融机构必须投资于可靠的存储解决方案,以确保长期数据的完整性和可访问性。 + +## 处理金融时序数据时面临的挑战 + +在时序数据处理领域,金融机构面临着一系列核心需求与挑战,这些需求与挑战不仅关系到日常运营的效率,还直接影响到决策的准确性和业务的创新能力。 + +- 高性能写入:金融机构需要的是一个能够实时处理巨量数据流的平台。随着交易活动的频繁和市场数据的不断更新,平台必须能够每秒处理数以亿计的数据点, +确保数据的即时性和完整性,以支持实时的交易决策和风险管理。 +- 强大的读取及数据消费性能:金融市场的特点是业务场景多变,这要求平台必须具备高度的数据读取和计算能力。例如,量化投资策略的研发依赖于实时行情数据和衍生数据的深度分析。平台需要支持高效的数据查询和计算,以便量化分析师能够快速回测模型、优化策略,并进行实时学习和调整。 +- 计算性能:资产和衍生品的监控对平台的计算性能提出了更高的要求。金融机构需要能够执行复杂的统计分析、风险预测和价格发现等计算任务,以监控市场动态和评估投资组合的风险。这要求平台不仅要有强大的计算能力,还要能够提供快速响应,以支持实时决策和快速反应市场变化。 + +## TDengine 在金融中的核心价值 + +TDengine,作为一个高性能、云原生的时序大数据平台,在金融行情数据处理领域表现卓越,为用户带来了显著的优势和收益。 +- 高写入性能:TDengine 实现了惊人的写入速度,达到每秒 1 亿数据点,确保在数据高峰时段也能够保持稳定的写入性能,满足金融市场对实时数据处理的严苛要求。 +- 高可用性:通过采用多副本技术和节点数据一致性机制,TDengine 提供了高可用性保障,确保在任何节点故障或网络异常情况下,数据都不会丢失,服务能够持 +续不间断。 +- 高查询性能:TDengine 的读取速度极快,单张子表的查询响应时间可在 1ms 内完成,满足金融分析师和交易系统对即时数据查询的迫切需求。 +- 高压缩率:利用先进的二级压缩和浮点数压缩技术,TDengine 大幅降低存储空间的需求和成本,同时保持数据的完整性和准确性,为金融机构节省大量的存储资源。 +- 赋能创新应用:在模型训练与验证的数据获取场景中,用户需要灵活选取任意时间段进行数据查询。TDengine 保持了全时间轴的无差异读取性能,极大地提高了数据的利用效能,加速了金融产品和服务的创新。 +- 支持国产化:TDengine 适配并兼容国产 CPU 和操作系统,支持国产化替代,符合国内金融行业对于自主可控的技术发展趋势,增强了金融机构在技术选择上的灵活性和安全性。 + +## TDengine 在金融中的应用 + +### 量化交易 + +随着科技的飞速发展,量化交易平台已经成为交易者在复杂金融市场中捕捉机遇、规避风险的重要工具。这些平台通过精确的市场分析和及时的响应机制,使交易者能够在瞬息万变的市场中把握投资机会,实现资产的稳定增值。在全球金融市场竞争日益激烈的背景下,基于行情数据的量化交易平台正逐渐成为投资者手中的一把利剑,为他们提供竞争优势。 + +特别是在金融科技取得突破性进展的今天,量化交易已成为资本市场中一股不可逆转的趋势。基于行情数据的量化交易平台,凭借其全面的应用模块和深入的数据应用能力,为金融市场提供了精准的分析和智能化的决策支持。这些平台不仅能够处理海量的市场数据,还能够运用先进的算法和模型,为交易者提供个性化的投资策略和风险管理方案。 + +在此背景下,TDengine作为一个专为时序数据设计的高性能数据库,其在量化交易平台中的应用,进一步提高了平台的性能和效率。TDengine的主要模块或功能如下。 + +1. 多路校验 + +TDengine 中的多路校验是一系列精心设计的特性,旨在确保金融行情数据的准确性和一致性,同时为风险管理提供坚实的数据支持。以下是这一功能的关键特性。 +- 确保行情数据的真实性与一致性:在金融交易中,数据的准确性和一致性至关重要。多路校验通过比对来自不同渠道的数据,确保数据的真实性,防止因数据错误导致的误判和投资失误。 +- 提供数据对比分析:多路校验允许用户对来自不同来源的数据进行深入对比分析,以检测潜在的数据偏差或错误。这种分析有助于及时发现并纠正数据问题,确保决策基于准确无误的信息。 +- 减少异常数据导致的投资失误:金融市场中的异常数据可能会误导投资者,导致错误的交易决策。多路校验通过消除异常数据,提高了数据的质量和可靠性,从而降低因数据问题导致的投资风险。 + +2. 数据血缘 + +TDengine 中的数据血缘是一组强大的特性,它们共同确保了数据的可追溯性、透明度和可靠性,为金融行业的数据处理和风险管理提供了坚实的基础。以下是数据血缘的关键特性。 +- 数据可追溯性:数据血缘允许用户追踪数据的起源和流转路径,确保每一条数据的来源都是清晰可辨的。这种可追溯性对于验证数据的准确性、审计数据变更历史以及追踪潜在的数据错误至关重要。 +- 数据转换逻辑与依赖关系分析:借助 TDengine 的高效计算能力,用户可以对数据进行深度分析,揭示数据在转换过程中的逻辑链条和依赖关系。这有助于用户理解数据的生成过程,识别潜在的数据处理瓶颈,并优化数据处理流程。 +- 提高数据处理的透明度和可靠性:通过在 TDengine 中存储数据,用户可以获得一个统一、可靠的数据视图。TDengine 的高性能和高可用性确保了数据处理的透明度和可靠性,使得客户在进行复杂的数据分析时能够信任所依赖的数据源。 + +3. 智能监控和分析 + +TDengine 中的智能监控和分析是一系列高级特性,它们共同构成了金融市场的实时监控和智能分析中心。以下是这些特性的介绍。 +- 实时监控与预警:TDengine 结合聚合计算和流计算技术,能够对市场动态、行情波动、交易异常等关键指标进行实时监控。通过设定阈值,系统能够及时发现异常情况并触发警报,帮助交易者和风险管理者迅速响应市场变化。 +- 智能分析与预测:利用 TDengine 的高速数据读取能力和先进的人工智能技术,系统可以对市场数据进行深度分析,预测市场走势,并提供潜在风险的及时警报。这种智能分析能力为投资决策提供了科学依据,提高了投资的前瞻性和预见性。 +- 自动调整交易策略:TDengine 的函数、UDF 和流计算功能,结合其他计算框架,使得交易策略能够根据市场实时数据自动调整。这种自适应的策略调整机制优化了资产配置,提高了交易的灵活性和效率。 +- 清晰的交易执行计划:通过对数据进行全面的计算分析,TDengine 能够输出清晰、明确的交易执行计划,为投资团队提供决策支持。这些计划结合了市场分析和风险评估,有助于团队制定出更加精准和有效的投资策略。 + +行情数据文件和实时数据流统一汇入TDengine集群后,客户可以通过HTTP接口轻松访问所有时序数据,构建各种金融服务应用。行情数据系统架构(见下图)不仅提供了数据的集中管理,还为开发者提供了开放的接口,使得构建复杂的数据分析工具和金融服务应用变得更加便捷和高效。通过这种架构,金融机构能够加快创新速度,提升服务质量,并在竞争激烈的金融市场中获得优势。 + +![行情数据系统架构](./finance-1.png) + +### 行情中心 + +行情中心在金融领域占据着举足轻重的地位,它构成了所有金融交易的基石,其性能的优劣直接影响着各类交易决策的正确与否。行情中心的主要职能涵盖数据采集、处理、持久化存储、分发以及展示,为证券投资、期货交易、量化投资、风险管理等下游业务提供至关重要的行情数据服务。其业务特点主要体现在以下几个方面。 + +- 实时性:行情中心必须实时处理股票市场的买卖信息和价格变动。对于投资者,能够即时获取最新的股票信息是做出快速而准确投资决策的关键。 +- 海量数据:随着交易市场的日益扩大和交易速度的不断提高,行情中心需要处理和分析的数据量呈现出爆炸性增长,这对数据处理能力提出了更高的要求。 +- 高并发:行情中心需要同时为众多应用提供高效的服务,必须具备强大的高并发处理能力。除了支持实时交易的核心业务以外,行情中心还须为量化回测、因子计算、风险管理等提供高效的时序数据服务。 +- 稳定性:作为金融市场的心脏,行情中心的稳定运行至关重要。任何形式的停机或故障都可能导致不可估量的经济损失。系统的高稳定性和可靠性是不可或缺的。众多券商在经过全面评估后,纷纷选择 TDengine 作为构建行情中心的核心组件,并且已经稳定运行多年。这一选择充分验证了 TDengine 在以下几个关键方面的卓越价值。 +- 实时性:TDengine 的高效写入能力能够处理大量的实时数据流,支持毫秒级甚至亚毫秒级的数据查询响应,完美契合行情中心对实时性的高标准要求。 +- 高并发处理:TDengine 设计了卓越的并发处理机制,能够支持从千万到亿级别的QPS(Queries Per Second,每秒查询率)的时序数据读写操作,确保了各类业务对实时和历史行情数据的写入和查询需求得到满足。 +- 海量数据处理能力:TDengine 的“一个数据采集点一张表”创新设计,结合先进的数据压缩技术和高效的存储格式,使得即使在存储超过 10 年历史数据的情况下,依然能够保持良好的读写性能,并且显著降低了存储空间的占用。 +- 稳定性:TDengine 提供了服务的高可用性和数据的强一致性保障,即使在单个节点发生故障的情况下,也能确保系统连续稳定运行,满足了行情中心对系统稳定性的严格要求。 + +这些券商的选择不仅体现了TDengine在技术性能上的领先地位,也彰显了对TDengine在金融行业中可靠性和适用性的广泛认可。通过采用TDengine,券商能够进一步提升行情中心的服务质量,增强核心竞争力,并在激烈的市场竞争中占据有利地位。 \ No newline at end of file diff --git a/docs/zh/25-application/01-telegraf.md b/docs/zh/25-application/_01-telegraf.md similarity index 100% rename from docs/zh/25-application/01-telegraf.md rename to docs/zh/25-application/_01-telegraf.md diff --git a/docs/zh/25-application/02-collectd.md b/docs/zh/25-application/_02-collected.md similarity index 100% rename from docs/zh/25-application/02-collectd.md rename to docs/zh/25-application/_02-collected.md diff --git a/docs/zh/25-application/03-immigrate.md b/docs/zh/25-application/_i3-immigrate.md similarity index 100% rename from docs/zh/25-application/03-immigrate.md rename to docs/zh/25-application/_i3-immigrate.md diff --git a/docs/zh/25-application/carnet.png b/docs/zh/25-application/carnet.png new file mode 100644 index 0000000000..26d5f9bee7 Binary files /dev/null and b/docs/zh/25-application/carnet.png differ diff --git a/docs/zh/25-application/distribution.png b/docs/zh/25-application/distribution.png new file mode 100644 index 0000000000..993f75ed25 Binary files /dev/null and b/docs/zh/25-application/distribution.png differ diff --git a/docs/zh/25-application/energy-data-in.png b/docs/zh/25-application/energy-data-in.png new file mode 100644 index 0000000000..ee2e4ce704 Binary files /dev/null and b/docs/zh/25-application/energy-data-in.png differ diff --git a/docs/zh/25-application/energy-distribution.png b/docs/zh/25-application/energy-distribution.png new file mode 100644 index 0000000000..7fe5a8a62c Binary files /dev/null and b/docs/zh/25-application/energy-distribution.png differ diff --git a/docs/zh/25-application/energy-kafka.png b/docs/zh/25-application/energy-kafka.png new file mode 100644 index 0000000000..098d52be16 Binary files /dev/null and b/docs/zh/25-application/energy-kafka.png differ diff --git a/docs/zh/25-application/finance-1.png b/docs/zh/25-application/finance-1.png new file mode 100644 index 0000000000..e05fae3f0b Binary files /dev/null and b/docs/zh/25-application/finance-1.png differ diff --git a/docs/zh/25-application/index.md b/docs/zh/25-application/index.md index 76aa179927..f49e6efae0 100644 --- a/docs/zh/25-application/index.md +++ b/docs/zh/25-application/index.md @@ -1,11 +1,5 @@ --- -title: 应用实践 -description: TDengine 配合其它开源组件的一些应用示例 ---- - -```mdx-code-block -import DocCardList from '@theme/DocCardList'; -import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; - - -``` \ No newline at end of file +title: 实践案例 +sidebar_label: 实践案例 +toc_max_heading_level: 4 +--- \ No newline at end of file diff --git a/docs/zh/25-application/manufacture-1.png b/docs/zh/25-application/manufacture-1.png new file mode 100644 index 0000000000..304d08fe0f Binary files /dev/null and b/docs/zh/25-application/manufacture-1.png differ diff --git a/docs/zh/25-application/manufacture-2.png b/docs/zh/25-application/manufacture-2.png new file mode 100644 index 0000000000..97162d2986 Binary files /dev/null and b/docs/zh/25-application/manufacture-2.png differ diff --git a/docs/zh/25-application/manufacture-3.png b/docs/zh/25-application/manufacture-3.png new file mode 100644 index 0000000000..a51bbafe8f Binary files /dev/null and b/docs/zh/25-application/manufacture-3.png differ diff --git a/docs/zh/25-application/oil-1.png b/docs/zh/25-application/oil-1.png new file mode 100644 index 0000000000..81d500238a Binary files /dev/null and b/docs/zh/25-application/oil-1.png differ diff --git a/docs/zh/25-application/oil-2.png b/docs/zh/25-application/oil-2.png new file mode 100644 index 0000000000..31644510bf Binary files /dev/null and b/docs/zh/25-application/oil-2.png differ diff --git a/docs/zh/20-third-party/01-grafana.mdx b/docs/zh/_20-third-party/01-grafana.mdx similarity index 100% rename from docs/zh/20-third-party/01-grafana.mdx rename to docs/zh/_20-third-party/01-grafana.mdx diff --git a/docs/zh/20-third-party/02-prometheus.md b/docs/zh/_20-third-party/02-prometheus.md similarity index 100% rename from docs/zh/20-third-party/02-prometheus.md rename to docs/zh/_20-third-party/02-prometheus.md diff --git a/docs/zh/20-third-party/03-telegraf.md b/docs/zh/_20-third-party/03-telegraf.md similarity index 100% rename from docs/zh/20-third-party/03-telegraf.md rename to docs/zh/_20-third-party/03-telegraf.md diff --git a/docs/zh/20-third-party/05-collectd.md b/docs/zh/_20-third-party/05-collectd.md similarity index 100% rename from docs/zh/20-third-party/05-collectd.md rename to docs/zh/_20-third-party/05-collectd.md diff --git a/docs/zh/20-third-party/06-statsd.md b/docs/zh/_20-third-party/06-statsd.md similarity index 100% rename from docs/zh/20-third-party/06-statsd.md rename to docs/zh/_20-third-party/06-statsd.md diff --git a/docs/zh/20-third-party/07-icinga2.md b/docs/zh/_20-third-party/07-icinga2.md similarity index 100% rename from docs/zh/20-third-party/07-icinga2.md rename to docs/zh/_20-third-party/07-icinga2.md diff --git a/docs/zh/20-third-party/08-tcollector.md b/docs/zh/_20-third-party/08-tcollector.md similarity index 100% rename from docs/zh/20-third-party/08-tcollector.md rename to docs/zh/_20-third-party/08-tcollector.md diff --git a/docs/zh/20-third-party/09-emq-broker.md b/docs/zh/_20-third-party/09-emq-broker.md similarity index 100% rename from docs/zh/20-third-party/09-emq-broker.md rename to docs/zh/_20-third-party/09-emq-broker.md diff --git a/docs/zh/20-third-party/10-hive-mq-broker.md b/docs/zh/_20-third-party/10-hive-mq-broker.md similarity index 100% rename from docs/zh/20-third-party/10-hive-mq-broker.md rename to docs/zh/_20-third-party/10-hive-mq-broker.md diff --git a/docs/zh/20-third-party/11-kafka.md b/docs/zh/_20-third-party/11-kafka.md similarity index 100% rename from docs/zh/20-third-party/11-kafka.md rename to docs/zh/_20-third-party/11-kafka.md diff --git a/docs/zh/20-third-party/12-google-data-studio.md b/docs/zh/_20-third-party/12-google-data-studio.md similarity index 100% rename from docs/zh/20-third-party/12-google-data-studio.md rename to docs/zh/_20-third-party/12-google-data-studio.md diff --git a/docs/zh/20-third-party/13-dbeaver.md b/docs/zh/_20-third-party/13-dbeaver.md similarity index 100% rename from docs/zh/20-third-party/13-dbeaver.md rename to docs/zh/_20-third-party/13-dbeaver.md diff --git a/docs/zh/20-third-party/50-qstudio.md b/docs/zh/_20-third-party/50-qstudio.md similarity index 100% rename from docs/zh/20-third-party/50-qstudio.md rename to docs/zh/_20-third-party/50-qstudio.md diff --git a/docs/zh/20-third-party/70-seeq.md b/docs/zh/_20-third-party/70-seeq.md similarity index 100% rename from docs/zh/20-third-party/70-seeq.md rename to docs/zh/_20-third-party/70-seeq.md diff --git a/docs/zh/20-third-party/75-powerbi.md b/docs/zh/_20-third-party/75-powerbi.md similarity index 100% rename from docs/zh/20-third-party/75-powerbi.md rename to docs/zh/_20-third-party/75-powerbi.md diff --git a/docs/zh/20-third-party/76-yonghongbi.mdx b/docs/zh/_20-third-party/76-yonghongbi.mdx similarity index 100% rename from docs/zh/20-third-party/76-yonghongbi.mdx rename to docs/zh/_20-third-party/76-yonghongbi.mdx diff --git a/docs/zh/20-third-party/_category_.yml b/docs/zh/_20-third-party/_category_.yml similarity index 100% rename from docs/zh/20-third-party/_category_.yml rename to docs/zh/_20-third-party/_category_.yml diff --git a/docs/zh/20-third-party/_deploytaosadapter.mdx b/docs/zh/_20-third-party/_deploytaosadapter.mdx similarity index 100% rename from docs/zh/20-third-party/_deploytaosadapter.mdx rename to docs/zh/_20-third-party/_deploytaosadapter.mdx diff --git a/docs/zh/20-third-party/add_datasource1.webp b/docs/zh/_20-third-party/add_datasource1.webp similarity index 100% rename from docs/zh/20-third-party/add_datasource1.webp rename to docs/zh/_20-third-party/add_datasource1.webp diff --git a/docs/zh/20-third-party/add_datasource2.webp b/docs/zh/_20-third-party/add_datasource2.webp similarity index 100% rename from docs/zh/20-third-party/add_datasource2.webp rename to docs/zh/_20-third-party/add_datasource2.webp diff --git a/docs/zh/20-third-party/add_datasource3.webp b/docs/zh/_20-third-party/add_datasource3.webp similarity index 100% rename from docs/zh/20-third-party/add_datasource3.webp rename to docs/zh/_20-third-party/add_datasource3.webp diff --git a/docs/zh/20-third-party/add_datasource4.webp b/docs/zh/_20-third-party/add_datasource4.webp similarity index 100% rename from docs/zh/20-third-party/add_datasource4.webp rename to docs/zh/_20-third-party/add_datasource4.webp diff --git a/docs/zh/20-third-party/alert-annotations.webp b/docs/zh/_20-third-party/alert-annotations.webp similarity index 100% rename from docs/zh/20-third-party/alert-annotations.webp rename to docs/zh/_20-third-party/alert-annotations.webp diff --git a/docs/zh/20-third-party/alert-email.webp b/docs/zh/_20-third-party/alert-email.webp similarity index 100% rename from docs/zh/20-third-party/alert-email.webp rename to docs/zh/_20-third-party/alert-email.webp diff --git a/docs/zh/20-third-party/alert-evaluation.webp b/docs/zh/_20-third-party/alert-evaluation.webp similarity index 100% rename from docs/zh/20-third-party/alert-evaluation.webp rename to docs/zh/_20-third-party/alert-evaluation.webp diff --git a/docs/zh/20-third-party/alert-feishu1.webp b/docs/zh/_20-third-party/alert-feishu1.webp similarity index 100% rename from docs/zh/20-third-party/alert-feishu1.webp rename to docs/zh/_20-third-party/alert-feishu1.webp diff --git a/docs/zh/20-third-party/alert-feishu2.webp b/docs/zh/_20-third-party/alert-feishu2.webp similarity index 100% rename from docs/zh/20-third-party/alert-feishu2.webp rename to docs/zh/_20-third-party/alert-feishu2.webp diff --git a/docs/zh/20-third-party/alert-labels.webp b/docs/zh/_20-third-party/alert-labels.webp similarity index 100% rename from docs/zh/20-third-party/alert-labels.webp rename to docs/zh/_20-third-party/alert-labels.webp diff --git a/docs/zh/20-third-party/alert-notification1.webp b/docs/zh/_20-third-party/alert-notification1.webp similarity index 100% rename from docs/zh/20-third-party/alert-notification1.webp rename to docs/zh/_20-third-party/alert-notification1.webp diff --git a/docs/zh/20-third-party/alert-notification2.webp b/docs/zh/_20-third-party/alert-notification2.webp similarity index 100% rename from docs/zh/20-third-party/alert-notification2.webp rename to docs/zh/_20-third-party/alert-notification2.webp diff --git a/docs/zh/20-third-party/alert-rules1.webp b/docs/zh/_20-third-party/alert-rules1.webp similarity index 100% rename from docs/zh/20-third-party/alert-rules1.webp rename to docs/zh/_20-third-party/alert-rules1.webp diff --git a/docs/zh/20-third-party/create_dashboard1.webp b/docs/zh/_20-third-party/create_dashboard1.webp similarity index 100% rename from docs/zh/20-third-party/create_dashboard1.webp rename to docs/zh/_20-third-party/create_dashboard1.webp diff --git a/docs/zh/20-third-party/create_dashboard2.webp b/docs/zh/_20-third-party/create_dashboard2.webp similarity index 100% rename from docs/zh/20-third-party/create_dashboard2.webp rename to docs/zh/_20-third-party/create_dashboard2.webp diff --git a/docs/zh/20-third-party/create_dashboard3.webp b/docs/zh/_20-third-party/create_dashboard3.webp similarity index 100% rename from docs/zh/20-third-party/create_dashboard3.webp rename to docs/zh/_20-third-party/create_dashboard3.webp diff --git a/docs/zh/20-third-party/dashboard-15146.webp b/docs/zh/_20-third-party/dashboard-15146.webp similarity index 100% rename from docs/zh/20-third-party/dashboard-15146.webp rename to docs/zh/_20-third-party/dashboard-15146.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-browse-cloud-data-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-browse-cloud-data-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-browse-cloud-data-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-browse-cloud-data-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-browse-data-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-browse-data-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-browse-data-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-browse-data-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-config-tdengine-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-config-tdengine-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-config-tdengine-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-config-tdengine-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-test-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-test-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-test-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-test-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-cloud-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-test-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-test-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-test-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-test-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-connect-tdengine-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-connect-tdengine-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-sql-execution-cloud-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-sql-execution-cloud-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-sql-execution-cloud-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-sql-execution-cloud-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/dbeaver-sql-execution-zh.webp b/docs/zh/_20-third-party/dbeaver/dbeaver-sql-execution-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/dbeaver-sql-execution-zh.webp rename to docs/zh/_20-third-party/dbeaver/dbeaver-sql-execution-zh.webp diff --git a/docs/zh/20-third-party/dbeaver/tdengine-cloud-jdbc-dsn-zh.webp b/docs/zh/_20-third-party/dbeaver/tdengine-cloud-jdbc-dsn-zh.webp similarity index 100% rename from docs/zh/20-third-party/dbeaver/tdengine-cloud-jdbc-dsn-zh.webp rename to docs/zh/_20-third-party/dbeaver/tdengine-cloud-jdbc-dsn-zh.webp diff --git a/docs/zh/20-third-party/emqx/add-action-handler.webp b/docs/zh/_20-third-party/emqx/add-action-handler.webp similarity index 100% rename from docs/zh/20-third-party/emqx/add-action-handler.webp rename to docs/zh/_20-third-party/emqx/add-action-handler.webp diff --git a/docs/zh/20-third-party/emqx/check-result-in-taos.webp b/docs/zh/_20-third-party/emqx/check-result-in-taos.webp similarity index 100% rename from docs/zh/20-third-party/emqx/check-result-in-taos.webp rename to docs/zh/_20-third-party/emqx/check-result-in-taos.webp diff --git a/docs/zh/20-third-party/emqx/check-rule-matched.webp b/docs/zh/_20-third-party/emqx/check-rule-matched.webp similarity index 100% rename from docs/zh/20-third-party/emqx/check-rule-matched.webp rename to docs/zh/_20-third-party/emqx/check-rule-matched.webp diff --git a/docs/zh/20-third-party/emqx/client-num.webp b/docs/zh/_20-third-party/emqx/client-num.webp similarity index 100% rename from docs/zh/20-third-party/emqx/client-num.webp rename to docs/zh/_20-third-party/emqx/client-num.webp diff --git a/docs/zh/20-third-party/emqx/create-resource.webp b/docs/zh/_20-third-party/emqx/create-resource.webp similarity index 100% rename from docs/zh/20-third-party/emqx/create-resource.webp rename to docs/zh/_20-third-party/emqx/create-resource.webp diff --git a/docs/zh/20-third-party/emqx/create-rule.webp b/docs/zh/_20-third-party/emqx/create-rule.webp similarity index 100% rename from docs/zh/20-third-party/emqx/create-rule.webp rename to docs/zh/_20-third-party/emqx/create-rule.webp diff --git a/docs/zh/20-third-party/emqx/edit-action.webp b/docs/zh/_20-third-party/emqx/edit-action.webp similarity index 100% rename from docs/zh/20-third-party/emqx/edit-action.webp rename to docs/zh/_20-third-party/emqx/edit-action.webp diff --git a/docs/zh/20-third-party/emqx/edit-resource.webp b/docs/zh/_20-third-party/emqx/edit-resource.webp similarity index 100% rename from docs/zh/20-third-party/emqx/edit-resource.webp rename to docs/zh/_20-third-party/emqx/edit-resource.webp diff --git a/docs/zh/20-third-party/emqx/login-dashboard.webp b/docs/zh/_20-third-party/emqx/login-dashboard.webp similarity index 100% rename from docs/zh/20-third-party/emqx/login-dashboard.webp rename to docs/zh/_20-third-party/emqx/login-dashboard.webp diff --git a/docs/zh/20-third-party/emqx/rule-engine.webp b/docs/zh/_20-third-party/emqx/rule-engine.webp similarity index 100% rename from docs/zh/20-third-party/emqx/rule-engine.webp rename to docs/zh/_20-third-party/emqx/rule-engine.webp diff --git a/docs/zh/20-third-party/emqx/rule-header-key-value.webp b/docs/zh/_20-third-party/emqx/rule-header-key-value.webp similarity index 100% rename from docs/zh/20-third-party/emqx/rule-header-key-value.webp rename to docs/zh/_20-third-party/emqx/rule-header-key-value.webp diff --git a/docs/zh/20-third-party/emqx/run-mock.webp b/docs/zh/_20-third-party/emqx/run-mock.webp similarity index 100% rename from docs/zh/20-third-party/emqx/run-mock.webp rename to docs/zh/_20-third-party/emqx/run-mock.webp diff --git a/docs/zh/20-third-party/gds/gds-01.webp b/docs/zh/_20-third-party/gds/gds-01.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-01.webp rename to docs/zh/_20-third-party/gds/gds-01.webp diff --git a/docs/zh/20-third-party/gds/gds-02.png.webp b/docs/zh/_20-third-party/gds/gds-02.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-02.png.webp rename to docs/zh/_20-third-party/gds/gds-02.png.webp diff --git a/docs/zh/20-third-party/gds/gds-03.png.webp b/docs/zh/_20-third-party/gds/gds-03.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-03.png.webp rename to docs/zh/_20-third-party/gds/gds-03.png.webp diff --git a/docs/zh/20-third-party/gds/gds-04.png.webp b/docs/zh/_20-third-party/gds/gds-04.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-04.png.webp rename to docs/zh/_20-third-party/gds/gds-04.png.webp diff --git a/docs/zh/20-third-party/gds/gds-05.png.webp b/docs/zh/_20-third-party/gds/gds-05.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-05.png.webp rename to docs/zh/_20-third-party/gds/gds-05.png.webp diff --git a/docs/zh/20-third-party/gds/gds-06.png.webp b/docs/zh/_20-third-party/gds/gds-06.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-06.png.webp rename to docs/zh/_20-third-party/gds/gds-06.png.webp diff --git a/docs/zh/20-third-party/gds/gds-07.png.webp b/docs/zh/_20-third-party/gds/gds-07.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-07.png.webp rename to docs/zh/_20-third-party/gds/gds-07.png.webp diff --git a/docs/zh/20-third-party/gds/gds-08.png.webp b/docs/zh/_20-third-party/gds/gds-08.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-08.png.webp rename to docs/zh/_20-third-party/gds/gds-08.png.webp diff --git a/docs/zh/20-third-party/gds/gds-09.png.webp b/docs/zh/_20-third-party/gds/gds-09.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-09.png.webp rename to docs/zh/_20-third-party/gds/gds-09.png.webp diff --git a/docs/zh/20-third-party/gds/gds-10.png.webp b/docs/zh/_20-third-party/gds/gds-10.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-10.png.webp rename to docs/zh/_20-third-party/gds/gds-10.png.webp diff --git a/docs/zh/20-third-party/gds/gds-11.png.webp b/docs/zh/_20-third-party/gds/gds-11.png.webp similarity index 100% rename from docs/zh/20-third-party/gds/gds-11.png.webp rename to docs/zh/_20-third-party/gds/gds-11.png.webp diff --git a/docs/zh/20-third-party/grafana-data-source.png b/docs/zh/_20-third-party/grafana-data-source.png similarity index 100% rename from docs/zh/20-third-party/grafana-data-source.png rename to docs/zh/_20-third-party/grafana-data-source.png diff --git a/docs/zh/20-third-party/grafana-install-and-config.png b/docs/zh/_20-third-party/grafana-install-and-config.png similarity index 100% rename from docs/zh/20-third-party/grafana-install-and-config.png rename to docs/zh/_20-third-party/grafana-install-and-config.png diff --git a/docs/zh/20-third-party/grafana-plugin-search-tdengine.png b/docs/zh/_20-third-party/grafana-plugin-search-tdengine.png similarity index 100% rename from docs/zh/20-third-party/grafana-plugin-search-tdengine.png rename to docs/zh/_20-third-party/grafana-plugin-search-tdengine.png diff --git a/docs/zh/20-third-party/import_dashboard.webp b/docs/zh/_20-third-party/import_dashboard.webp similarity index 100% rename from docs/zh/20-third-party/import_dashboard.webp rename to docs/zh/_20-third-party/import_dashboard.webp diff --git a/docs/zh/20-third-party/import_dashboard1.webp b/docs/zh/_20-third-party/import_dashboard1.webp similarity index 100% rename from docs/zh/20-third-party/import_dashboard1.webp rename to docs/zh/_20-third-party/import_dashboard1.webp diff --git a/docs/zh/20-third-party/import_dashboard2.webp b/docs/zh/_20-third-party/import_dashboard2.webp similarity index 100% rename from docs/zh/20-third-party/import_dashboard2.webp rename to docs/zh/_20-third-party/import_dashboard2.webp diff --git a/docs/zh/20-third-party/index.md b/docs/zh/_20-third-party/index.md similarity index 100% rename from docs/zh/20-third-party/index.md rename to docs/zh/_20-third-party/index.md diff --git a/docs/zh/20-third-party/kafka/Kafka_Connect.webp b/docs/zh/_20-third-party/kafka/Kafka_Connect.webp similarity index 100% rename from docs/zh/20-third-party/kafka/Kafka_Connect.webp rename to docs/zh/_20-third-party/kafka/Kafka_Connect.webp diff --git a/docs/zh/20-third-party/kafka/confluentPlatform.webp b/docs/zh/_20-third-party/kafka/confluentPlatform.webp similarity index 100% rename from docs/zh/20-third-party/kafka/confluentPlatform.webp rename to docs/zh/_20-third-party/kafka/confluentPlatform.webp diff --git a/docs/zh/20-third-party/kafka/streaming-integration-with-kafka-connect.webp b/docs/zh/_20-third-party/kafka/streaming-integration-with-kafka-connect.webp similarity index 100% rename from docs/zh/20-third-party/kafka/streaming-integration-with-kafka-connect.webp rename to docs/zh/_20-third-party/kafka/streaming-integration-with-kafka-connect.webp diff --git a/docs/zh/20-third-party/powerbi-step-zh.png b/docs/zh/_20-third-party/powerbi-step-zh.png similarity index 100% rename from docs/zh/20-third-party/powerbi-step-zh.png rename to docs/zh/_20-third-party/powerbi-step-zh.png diff --git a/docs/zh/20-third-party/qstudio/qstudio-browse-data.webp b/docs/zh/_20-third-party/qstudio/qstudio-browse-data.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-browse-data.webp rename to docs/zh/_20-third-party/qstudio/qstudio-browse-data.webp diff --git a/docs/zh/20-third-party/qstudio/qstudio-chart.webp b/docs/zh/_20-third-party/qstudio/qstudio-chart.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-chart.webp rename to docs/zh/_20-third-party/qstudio/qstudio-chart.webp diff --git a/docs/zh/20-third-party/qstudio/qstudio-connect-tdengine-test.webp b/docs/zh/_20-third-party/qstudio/qstudio-connect-tdengine-test.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-connect-tdengine-test.webp rename to docs/zh/_20-third-party/qstudio/qstudio-connect-tdengine-test.webp diff --git a/docs/zh/20-third-party/qstudio/qstudio-connect-tdengine.webp b/docs/zh/_20-third-party/qstudio/qstudio-connect-tdengine.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-connect-tdengine.webp rename to docs/zh/_20-third-party/qstudio/qstudio-connect-tdengine.webp diff --git a/docs/zh/20-third-party/qstudio/qstudio-jdbc-connector-download.webp b/docs/zh/_20-third-party/qstudio/qstudio-jdbc-connector-download.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-jdbc-connector-download.webp rename to docs/zh/_20-third-party/qstudio/qstudio-jdbc-connector-download.webp diff --git a/docs/zh/20-third-party/qstudio/qstudio-sql-execution.webp b/docs/zh/_20-third-party/qstudio/qstudio-sql-execution.webp similarity index 100% rename from docs/zh/20-third-party/qstudio/qstudio-sql-execution.webp rename to docs/zh/_20-third-party/qstudio/qstudio-sql-execution.webp diff --git a/docs/zh/20-third-party/seeq/seeq-demo-schema.webp b/docs/zh/_20-third-party/seeq/seeq-demo-schema.webp similarity index 100% rename from docs/zh/20-third-party/seeq/seeq-demo-schema.webp rename to docs/zh/_20-third-party/seeq/seeq-demo-schema.webp diff --git a/docs/zh/20-third-party/seeq/seeq-demo-workbench.webp b/docs/zh/_20-third-party/seeq/seeq-demo-workbench.webp similarity index 100% rename from docs/zh/20-third-party/seeq/seeq-demo-workbench.webp rename to docs/zh/_20-third-party/seeq/seeq-demo-workbench.webp diff --git a/docs/zh/20-third-party/seeq/seeq-forecast-result.webp b/docs/zh/_20-third-party/seeq/seeq-forecast-result.webp similarity index 100% rename from docs/zh/20-third-party/seeq/seeq-forecast-result.webp rename to docs/zh/_20-third-party/seeq/seeq-forecast-result.webp diff --git a/docs/zh/20-third-party/seeq/seeq-workbench-with-tdengine-cloud.webp b/docs/zh/_20-third-party/seeq/seeq-workbench-with-tdengine-cloud.webp similarity index 100% rename from docs/zh/20-third-party/seeq/seeq-workbench-with-tdengine-cloud.webp rename to docs/zh/_20-third-party/seeq/seeq-workbench-with-tdengine-cloud.webp diff --git a/docs/zh/20-third-party/yonghongbi-step-zh.png b/docs/zh/_20-third-party/yonghongbi-step-zh.png similarity index 100% rename from docs/zh/20-third-party/yonghongbi-step-zh.png rename to docs/zh/_20-third-party/yonghongbi-step-zh.png