Merge pull request #29813 from taosdata/doc/contrib

doc: minor changes
This commit is contained in:
Shengliang Guan 2025-02-18 15:41:23 +08:00 committed by GitHub
commit b31eeecd1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 127 additions and 129 deletions

View File

@ -1,5 +1,5 @@
---
sidebar_label: 用Docker快速体验
sidebar_label: 用 Docker 快速体验
title: 用 Docker 快速体验 TDengine
description: 使用 Docker 快速体验 TDengine 的高效写入和查询
---
@ -91,7 +91,7 @@ taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如
taosBenchmark --help
```
有关taosBenchmark 的详细使用方法,请参考[taosBenchmark 参考手册](../../reference/tools/taosbenchmark)
有关 taosBenchmark 的详细使用方法,请参考 [taosBenchmark 参考手册](../../reference/tools/taosbenchmark)
### 体验查询

View File

@ -17,30 +17,27 @@ TDengine 完整的软件包包括服务端taosd、应用驱动taosc
此外TDengine 也提供 macOS x64/m1 平台的 pkg 安装包。
## 运行环境要求
在linux系统中运行环境最低要求如下:
1. linux 内核版本3.10.0-1160.83.1.el7.x86_64 或以上
2. glibc 版本2.17 或以上
linux 内核版本 - 3.10.0-1160.83.1.el7.x86_64;
glibc 版本 - 2.17;
如果通过clone源码进行编译安装还需要满足:
cmake版本 - 3.26.4或以上;
gcc 版本 - 9.3.1或以上;
如果通过 Clone 源码进行编译安装,还需要满足:
1. cmake 版本3.26.4 或以上
2. gcc 版本9.3.1 或以上
## 安装
**注意**
从TDengine 3.0.6.0 开始,不再提供单独的 taosTools 安装包,原 taosTools 安装包中包含的工具都在 TDengine-server 安装包中,如果需要请直接下载 TDengine -server 安装包。
从 TDengine 3.0.6.0 开始,不再提供单独的 taosTools 安装包,原 taosTools 安装包中包含的工具都在 TDengine-server 安装包中,如果需要请直接下载 TDengine-server 安装包。
<Tabs>
<TabItem label="Deb 安装" value="debinst">
1. 从列表中下载获得 Deb 安装包
1. 从列表中下载获得 Deb 安装包
<PkgListV3 type={6}/>
2. 进入到安装包所在目录,执行如下的安装命令:
> 请将 `<version>` 替换为下载的安装包版本
@ -53,8 +50,9 @@ sudo dpkg -i TDengine-server-<version>-Linux-x64.deb
<TabItem label="RPM 安装" value="rpminst">
1. 从列表中下载获得 RPM 安装包
1. 从列表中下载获得 RPM 安装包
<PkgListV3 type={5}/>
2. 进入到安装包所在目录,执行如下的安装命令:
> 请将 `<version>` 替换为下载的安装包版本
@ -67,7 +65,7 @@ sudo rpm -ivh TDengine-server-<version>-Linux-x64.rpm
<TabItem label="tar.gz 安装" value="tarinst">
1. 从列表中下载获得 tar.gz 安装包
1. 从列表中下载获得 tar.gz 安装包
<PkgListV3 type={0}/>
2. 进入到安装包所在目录,使用 `tar` 解压安装包;
3. 进入到安装包所在目录,先解压文件后,进入子目录,执行其中的 install.sh 安装脚本。
@ -126,14 +124,14 @@ apt-get 方式只适用于 Debian 或 Ubuntu 系统。
**注意**
- 目前 TDengine 在 Windows 平台上只支持 Windows Server 2016/2019 和 Windows 10/11。
- 从 TDengine 3.1.0.0 开始,只提供 Windows 客户端安装包。如果需要 Windows 服务端安装包,请联系 TDengine 销售团队升级为企业版。
- Windows 上需要安装 VC 运行时库,可在此下载安装 [VC运行时库](https://learn.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redist?view=msvc-170), 如果已经安装此运行库可忽略。
- Windows 上需要安装 VC 运行时库,可在此下载安装 [VC 运行时库](https://learn.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redist?view=msvc-170)如果已经安装此运行库可忽略。
按照以下步骤安装:
1. 从列表中下载获得 exe 安装程序
1. 从列表中下载获得 exe 安装程序
<PkgListV3 type={3}/>
2. 运行可执行程序来安装 TDengine。
Note: 从 3.0.1.7 开始,只提供 TDengine 客户端的 Windows 客户端的下载。想要使用TDengine 服务端的 Windows 版本,请联系销售升级为企业版
Note: 从 3.0.1.7 版本开始,只提供 TDengine 客户端的 Windows 客户端的下载。想要使用 TDengine 服务端的 Windows 版本,请联系 TDengine 销售团队升级为企业版。
</TabItem>
<TabItem label="macOS 安装" value="macos">
@ -210,12 +208,12 @@ sudo launchctl start com.tdengine.taoskeeper
sudo launchctl start com.tdengine.taos-explorer
```
你也可以直接运行 start-all.sh 脚本来启动上面的所有服务
你也可以直接运行 `start-all.sh` 脚本来启动上面的所有服务
```bash
start-all.sh
```
可以使用 `launchctl` 命令管理上面提到的每个 TDengine 服务,以下示例使用 `taosd`
可以使用 `launchctl` 命令管理上面提到的每个 TDengine 服务,以下示例使用 `taosd`
```bash
sudo launchctl start com.tdengine.taosd

View File

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

View File

@ -25,11 +25,11 @@ toc_max_heading_level: 4
### 采集量
采集量是指通过各种传感器、设备或其他类型的采集点所获取的物理量如电流、电压、温度、压力、GPS 等。由于这些物理量随时间不断变化,因此采集的数据类型多
样,包括整型、浮点型、布尔型以及字符串等。随着时间的积累,存储的数据将持续增长。以智能电表为例,其中的 current电流、voltage电压和 phase相位便是典型的采集量。
样,包括整型、浮点型、布尔型以及字符串等。随着时间的积累,存储的数据将持续增长。以智能电表为例,其中的 current、voltage 和 phase 便是典型的采集量。
### 标签
标签是指附着在传感器、设备或其他类型采集点上的静态属性这些属性不会随时间发生变化例如设备型号、颜色、设备所在地等。标签的数据类型可以是任意类型。尽管标签本身是静态的但在实际应用中用户可能需要对标签进行修改、删除或添加。与采集量不同随着时间的推移存储的标签数据量保持相对稳定不会呈现明显的增长趋势。在智能电表的示例中location(位置)和 Group ID分组 ID就是典型的标签。
标签是指附着在传感器、设备或其他类型采集点上的静态属性这些属性不会随时间发生变化例如设备型号、颜色、设备所在地等。标签的数据类型可以是任意类型。尽管标签本身是静态的但在实际应用中用户可能需要对标签进行修改、删除或添加。与采集量不同随着时间的推移存储的标签数据量保持相对稳定不会呈现明显的增长趋势。在智能电表的示例中location 和 Group ID 就是典型的标签。
### 数据采集点
@ -49,9 +49,9 @@ toc_max_heading_level: 4
4. 一个数据块内部,采用列式存储,对于不同的数据类型,可以采用不同压缩算法来提高压缩率。并且,由于采集量的变化通常是缓慢的,压缩率会更高。
如果采用传统的方式,将多个数据采集点的数据写入一张表,由于网络延时不可控,不同数据采集点的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个数据采集点的数据是难以保证连续存储在一起的。采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的,而且数据压缩率最高。
如果采用传统的方式,将多个数据采集点的数据写入一张表,由于网络延时不可控,不同数据采集点的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个数据采集点的数据是难以保证连续存储在一起的。采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的,而且数据压缩率最高。
在 TDengine 中,通常使用数据采集点的名称(如d1001来做表名每个数据采集点可以有多个采集量current、voltage、phase 等),每个采集量对应一张表的一列。采集量的数据类型可以是整型、浮点型、字符串等。
在 TDengine 中,通常使用数据采集点的名称(如 d1001来做表名每个数据采集点可以有多个采集量current、voltage、phase 等),每个采集量对应一张表的一列。采集量的数据类型可以是整型、浮点型、字符串等。
此外,表的第一列必须是时间戳,即数据类型为 Timestamp。对于每个采集量TDengine 将使用第一列时间戳建立索引,采用列式存储。对于复杂的设备,比如汽车,它有多个数据采集点,则需要为一辆汽车建立多张表。
@ -86,12 +86,12 @@ toc_max_heading_level: 4
### 时间戳
时间戳在时序数据处理中扮演着至关重要的角色,特别是在应用程序需要从多个不同时区访问数据库时,这一问题变得更加复杂。在深入了解 TDengine 如何处理时间戳与时区之前,我们先介绍以下几个基本概念。
- 本地日期时间:指特定地区的当地时间,通常表示为 yyyy-MM-dd hh:mm:ss.SSS 格 串。 息, 如“2021-07-21 12:00:00.000”。
- 时区地球上不同地理位置的标准时间。协调世界时Universal Time CoordinatedUTC或格林尼治时间是国际时间标准其他时区通常表示为相对于 UTC 的偏移量如“UTC+8”代表东八区时间。 UTC 时间戳:表示自 UNIX 纪 元(即 UTC 时 间 1970 年 1 月 1 日 0 点) 过的毫秒数。例如“1700000000000”对应的日期时间是“2023-11-14 22:13:20UTC+0”。 在 TDengine 中保存时序数据时,实际上保存的是 UTC 时间戳。TDengine 在写入数据时,时间戳的处理分为如下两种情况。
- RFC-3339 格式当使用这种格式时TDengine 能够正确解析带有时区信息的时间字符串为 UTC 时间戳。例如“2018-10-03T14:38:05.000+08:00”会被转换为UTC 时间戳。
- 本地日期时间:指特定地区的当地时间,通常表示为 yyyy-MM-dd hh:mm:ss.SSS 格式的字符串。这种时间表示不包含任何时区信息,如 “2021-07-21 12:00:00.000”。
- 时区地球上不同地理位置的标准时间。协调世界时Universal Time CoordinatedUTC或格林尼治时间是国际时间标准其他时区通常表示为相对于 UTC 的偏移量,如 “UTC+8” 代表东八区时间。 UTC 时间戳:表示自 UNIX 纪元(即 UTC 时间 1970 年 1 月 1 日 0 点起经过的毫秒数。例如“1700000000000” 对应的日期时间是 “2023-11-14 22:13:20UTC+0”。 在 TDengine 中保存时序数据时,实际上保存的是 UTC 时间戳。TDengine 在写入数据时,时间戳的处理分为如下两种情况。
- RFC-3339 格式当使用这种格式时TDengine 能够正确解析带有时区信息的时间字符串为 UTC 时间戳。例如“2018-10-03T14:38:05.000+08:00” 会被转换为 UTC 时间戳。
- 非 RFC-3339 格式如果时间字符串不包含时区信息TDengine 将使用应用程序所在的时区设置自动将时间转换为 UTC 时间戳。
在查询数据时TDengine 客户端会根据应用程序当前的时区设置自动将保存的UTC 时间戳转换成本地时间进行显示,确保用户在不同时区下都能看到正确的时间信息。
在查询数据时TDengine 客户端会根据应用程序当前的时区设置,自动将保存的 UTC 时间戳转换成本地时间进行显示,确保用户在不同时区下都能看到正确的时间信息。
## 数据建模
@ -110,7 +110,7 @@ CREATE DATABASE power PRECISION 'ms' KEEP 3650 DURATION 10 BUFFER 16;
- `DURATION 10` :每 10 天的数据放在一个数据文件中
- `BUFFER 16` :写入使用大小为 16MB 的内存池。
在创建power数据库后可以执行 USE 语句来使用切换数据库。
在创建 power 数据库后,可以执行 USE 语句来使用切换数据库。
```sql
use power;
@ -134,10 +134,10 @@ CREATE STABLE meters (
在 TDengine 中,创建超级表的 SQL 语句与关系型数据库类似。例如,上面的 SQL 中,`CREATE STABLE` 为关键字,表示创建超级表;接着,`meters` 是超级表的名称;在表名后面的括号中,定义超级表的列(列名、数据类型等),规则如下:
1. 第 1 列必须为时间戳列。例如:`ts timestamp` 表示,时间戳列名是 `t`s,数据类型为 `timestamp`
2. 第 2 列开始是采集量列。采集量的数据类型可以为整型、浮点型、字符串等。例如:`current float` 表示,采集量电流 `current`,数据类型为 `float`
1. 第 1 列必须为时间戳列。例如:`ts timestamp` 表示,时间戳列名是 `ts`,数据类型为 `timestamp`
2. 第 2 列开始是采集量列。采集量的数据类型可以为整型、浮点型、字符串等。例如:`current float` 表示,采集量电流 `current`,数据类型为 `float`
最后TAGS是关键字表示标签在 TAGS 后面的括号中,定义超级表的标签(标签名、数据类型等)。
最后TAGS 是关键字,表示标签,在 TAGS 后面的括号中,定义超级表的标签(标签名、数据类型等)。
1. 标签的数据类型可以为整型、浮点型、字符串等。例如:`location varchar(64)` 表示,标签地区 `location`,数据类型为 `varchar(64)`
2. 标签的名称不能与采集量列的名称相同。
@ -155,7 +155,7 @@ USING meters (
);
```
上面的 SQL 中,`CREATE TABLE` 为关键字,表示创建表;`d1001` 是子表的名称;`USING` 是关键字,表示要使用超级表作为模版;`meters` 是超级表的名称;在超级表名后的括号中,`location`, `group_id` 表示,是超级表的标签列名列表;`TAGS` 是关键字,在后面的括号中指定子表的标签列的值。`"California.SanFrancisco"` 和 `2` 表示子表 `d1001` 的位置为 `California.SanFrancisco`,分组 ID 为 `2`
上面的 SQL 中,`CREATE TABLE` 为关键字,表示创建表;`d1001` 是子表的名称;`USING` 是关键字,表示要使用超级表作为模版;`meters` 是超级表的名称;在超级表名后的括号中,`location`、`group_id` 表示,是超级表的标签列名列表;`TAGS` 是关键字,在后面的括号中指定子表的标签列的值。`"California.SanFrancisco"` 和 `2` 表示子表 `d1001` 的位置为 `California.SanFrancisco`,分组 ID 为 `2`
当对超级表进行写入或查询操作时,用户可以使用伪列 tbname 来指定或输出对应操作的子表名。
@ -178,7 +178,7 @@ TAGS (
);
```
上面的 SQL 中,`INSERT INTO d1002` 表示,向子表 `d1002` 中写入数据;`USING meters` 表示,使用超级表 `meters` 作为模版;`TAGS ("California.SanFrancisco", 2)` 表示,子表 `d1002` 的标签值分别为 `California.SanFrancisco``2``VALUES (NOW, 10.2, 219, 0.32)` 表示,向子表 `d1002` 插入一行记录值分别为NOW当前时间戳、10.2电流、219电压、0.32(相位)。在 TDengine 执行这条 SQL 时,如果子表 `d1002` 已经存在,则直接写入数据;当子表 `d1002` 不存在,会先自动创建子表,再写入数据。
上面的 SQL 中,`INSERT INTO d1002` 表示,向子表 `d1002` 中写入数据;`USING meters` 表示,使用超级表 `meters` 作为模版;`TAGS ("California.SanFrancisco", 2)` 表示,子表 `d1002` 的标签值分别为 `California.SanFrancisco``2``VALUES (NOW, 10.2, 219, 0.32)` 表示,向子表 `d1002` 插入一行记录,值分别为 NOW当前时间戳、10.2电流、219电压、0.32(相位)。在 TDengine 执行这条 SQL 时,如果子表 `d1002` 已经存在,则直接写入数据;当子表 `d1002` 不存在,会先自动创建子表,再写入数据。
### 创建普通表
@ -204,7 +204,7 @@ CREATE TABLE d1003(
);
```
上面的 SQL 表示,创建普通表 `d1003` ,表结构包括 `ts`、`current`、`voltage`、`phase`、`location`、`group_id`,共 6 个列。这样的数据模型,与关系型数据库完全一致。
上面的 SQL 表示,创建普通表 `d1003`,表结构包括 `ts`、`current`、`voltage`、`phase`、`location`、`group_id`,共 6 个列。这样的数据模型,与关系型数据库完全一致。
采用普通表作为数据模型意味着静态标签数据(如 location 和 group_id会重复存储在表的每一行中。这种做法不仅增加了存储空间的消耗而且在进行查询时由于无法直接利用标签数据进行过滤查询性能会显著低于使用超级表的数据模型。

View File

@ -12,9 +12,9 @@ toc_max_heading_level: 4
### 一次写入一条
假设设备 ID 为 d1001 的智能电表在 2018 年 10 月 3 日 14:38:05 采集到数据电流10.3A,电压 219V相位 0.31。在第 3 章中,我们已经在 TDengine 的 power 数据库中创建了属于超级表 meters 的子表 d1001。接下来可以通过下面的 insert 语句在子表 d1001 中写入时序数据。
假设设备 ID 为 d1001 的智能电表在 2018 年 10 月 3 日 14:38:05 采集到数据:电流 10.3A,电压 219V相位 0.31。在第 3 章中,我们已经在 TDengine 的 power 数据库中创建了属于超级表 meters 的子表 d1001。接下来可以通过下面的 insert 语句在子表 d1001 中写入时序数据。
1. 可以通过下面的 INSERT 语句向子表d1001中写入时序数据。
1. 可以通过下面的 INSERT 语句向子表 d1001 中写入时序数据。
```sql
insert into d1001 (ts, current, voltage, phase) values ( "2018-10-03 14:38:05", 10.3, 219, 0.31)
@ -120,7 +120,7 @@ values( "d1001, "2018-10-03 14:38:05", 10.2, 220, 0.23, "California.SanFrancisco
## 更新
可以通过写入重复时间戳的一条数据来更新时序数据,新写入的数据会替换旧值。 下面的 SQL通过指定列的方式向子表 `d1001` 中写入 1 行数据;当子表 `d1001` 中已经存在日期时间为 `2018-10-03 14:38:05` 的数据时,`current`电流的新值22会替换旧值。
可以通过写入重复时间戳的一条数据来更新时序数据,新写入的数据会替换旧值。下面的 SQL通过指定列的方式向子表 `d1001` 中写入 1 行数据;当子表 `d1001` 中已经存在日期时间为 `2018-10-03 14:38:05` 的数据时,`current`(电流)的新值 22会替换旧值。
```sql
INSERT INTO d1001 (ts, current) VALUES ("2018-10-03 14:38:05", 22);
@ -128,7 +128,7 @@ INSERT INTO d1001 (ts, current) VALUES ("2018-10-03 14:38:05", 22);
## 删除
为方便用户清理由于设备故障等原因产生的异常数据TDengine 支持根据时间戳删除时序数据。 下面的 SQL将超级表 `meters` 中所有时间戳早于 `2021-10-01 10:40:00.100` 的数据删除。数据删除后不可恢复,请慎重使用。为了确保删除的数据确实是自己要删除的,建议可以先使用 select 语句加 where 后的删除条件查看要删除的数据内容,确认无误后再执行 delete 。
为方便用户清理由于设备故障等原因产生的异常数据TDengine 支持根据时间戳删除时序数据。下面的 SQL将超级表 `meters` 中所有时间戳早于 `2021-10-01 10:40:00.100` 的数据删除。数据删除后不可恢复,请慎重使用。为了确保删除的数据确实是自己要删除的,建议可以先使用 select 语句加 where 后的删除条件查看要删除的数据内容,确认无误后再执行 delete 。
```sql
delete from meters where ts < '2021-10-01 10:40:00.100' ;

View File

@ -14,7 +14,7 @@ toc_max_heading_level: 4
taosBenchmark --start-timestamp=1600000000000 --tables=100 --records=10000000 --time-step=10000
```
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的数据库,产生共 10 亿条时序数据。时序数据的时间戳从 `1600000000000`2020-09-13T20:26:40+08:00开始包含 `100` 个设备(子表),每个设备有 `10000000` 条数据,时序数据的采集频率是 10 秒/ 条。
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的数据库,产生共 10 亿条时序数据。时序数据的时间戳从 `1600000000000`2020-09-13T20:26:40+08:00开始包含 `100` 个设备(子表),每个设备有 `10000000` 条数据,时序数据的采集频率是 10 秒/条。
在 TDengine 中,用户可以通过 WHERE 语句指定条件,查询时序数据。以智能电表的数据为例
@ -74,22 +74,22 @@ GROUP BY groupid;
Query OK, 10 row(s) in set (0.042446s)
```
**注意**: group by 子句在聚合数据时,并不保证结果集按照特定顺序排列。为了获得有序的结果集,可以使用 order by 子句对结果进行排序。这样,可以根据需要调整输出结果的顺序,以满足特定的业务需求或报告要求。
**注意**group by 子句在聚合数据时,并不保证结果集按照特定顺序排列。为了获得有序的结果集,可以使用 order by 子句对结果进行排序。这样,可以根据需要调整输出结果的顺序,以满足特定的业务需求或报告要求。
TDengine 提供了多种内置的聚合函数。如下表所示:
| 聚合函数 | 功能说明 |
|:----------------------:|:--------------------------------------------------------------:|
|APERCENTILE | 统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。 |
|AVG | 统计指定字段的平均值 |
|COUNT | 统计指定字段的记录行数 |
|APERCENTILE | 统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。|
|AVG | 统计指定字段的平均值|
|COUNT | 统计指定字段的记录行数|
|ELAPSED|elapsed 函数表达了统计周期内连续的时间长度,和 twa 函数配合使用可以计算统计曲线下的面积。在通过 INTERVAL 子句指定窗口的情况下,统计在给定时间范围内的每个窗口内有数据覆盖的时间范围;如果没有 INTERVAL 子句则返回整个给定时间范围内的有数据覆盖的时间范围。注意ELAPSED 返回的并不是时间范围的绝对值,而是绝对值除以 time_unit 所得到的单位个数。|
|LEASTSQUARES | 统计表中某列的值的拟合直线方程。start_val 是自变量初始值step_val 是自变量的步长值。 |
|LEASTSQUARES | 统计表中某列的值的拟合直线方程。start_val 是自变量初始值step_val 是自变量的步长值。|
|SPREAD | 统计表中某列的最大值和最小值之差。|
|STDDEV | 统计表中某列的均方差。 |
|SUM | 统计表/超级表中某列的和。 |
|HYPERLOGLOG | 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。在数据量较少的时候该算法不是很准确,可以使用 select countdata from select uniquecol as data from table 的方法。 |
|HISTOGRAM | 统计数据按照用户指定区间的分布。 |
|STDDEV | 统计表中某列的均方差。|
|SUM | 统计表/超级表中某列的和。|
|HYPERLOGLOG | 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。在数据量较少的时候该算法不是很准确,可以使用 select count(data) from (select unique(col) as data from table) 的方法。|
|HISTOGRAM | 统计数据按照用户指定区间的分布。|
|PERCENTILE | 统计表中某列的值百分比分位数。|
## 数据切分查询
@ -101,12 +101,12 @@ PARTITION BY part_list
`part_list` 可以是任意的标量表达式,包括列、常量、标量函数和它们的组合。
TDengine 按如下方式处理数据切分子句
TDengine 按如下方式处理数据切分子句
1. 数据切分子句位于 WHERE 子句之后;
2. 数据切分子句将表数据按指定的维度进行切分每个切分的分片进行指定的计算。计算由之后的子句定义窗口子句、GROUP BY 子句或 SELECT 子句);
3. 数据切分子句可以和窗口切分子句(或 GROUP BY 子句)一起使用,此时后面的子句作用在每个切分的分片上。
数据切分的 SQL 如下:s
数据切分的 SQL 如下:
```sql
SELECT location, avg(voltage)
@ -141,6 +141,7 @@ Query OK, 10 row(s) in set (2.415961s)
- 状态窗口status window
- 会话窗口session window
- 事件窗口event window
- 计数窗口count window
窗口划分逻辑如下图所示:
@ -152,14 +153,15 @@ Query OK, 10 row(s) in set (2.415961s)
window_clause: {
SESSION(ts_col, tol_val)
| STATE_WINDOW(col)
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [WATERMARK(watermark_val)] [FILL(fill_mod_and_val)]
| EVENT_WINDOW START WITH start_trigger_condition END WITH end_trigger_condition
| COUNT_WINDOW(count_val[, sliding_val])
}
```
**注意** 在使用窗口子句时应注意以下规则:
1. 窗口子句位于数据切分子句之后,不可以和 GROUP BY 子句一起使用。
2. 窗口子句将数据按窗口进行切分,对每个窗口进行 SELECT 列表中的表达式的计算SELECT 列表中的表达式只能包含常量伪列_wstart 伪列、_wend 伪列和 _wduration 伪列;聚合函数(包括选择函数和可以由参数确定输出行数的时序特有函数)
2. 窗口子句将数据按窗口进行切分,对每个窗口进行 SELECT 列表中的表达式的计算SELECT 列表中的表达式只能包含常量伪列_wstart、_wend 和 _wduration聚合函数包括选择函数和可以由参数确定输出行数的时序特有函数。
3. WHERE 语句可以指定查询的起止时间和其他过滤条件。
### 时间戳伪列
@ -177,16 +179,15 @@ INTERVAL(interval_val [, interval_offset])
```
时间窗口子句包括 3 个子句:
- INTERVAL 子句用于产生相等时间周期的窗口interval_val 指定每个时间窗口的大小interval_offset 指定;
- INTERVAL 子句用于产生相等时间周期的窗口interval_val 指定每个时间窗口的大小interval_offset 指定窗口偏移量
- SLIDING 子句:用于指定窗口向前滑动的时间;
- FILL用于指定窗口区间数据缺失的情况下数据的填充模式。
对于时间窗口interval_val 和 sliding_val 都表示时间段, 语法上支持三种方式。例如:
1. INTERVAL(1s, 500a) SLIDING(1s),带时间单位的形式,其中的时间单位是单字符表示, 分别为: a (毫秒), b (纳秒), d (天), h (小时), m (分钟), n (月), s (秒), u (微秒), w (周), y (年);
对于时间窗口interval_val 和 sliding_val 都表示时间段,语法上支持三种方式。例如:
1. INTERVAL(1s, 500a) SLIDING(1s),带时间单位的形式,其中的时间单位是单字符表示,分别为a毫秒、b纳秒d、h小时、m分钟、n、s、u微秒、w、y(年);
2. INTERVAL(1000, 500) SLIDING(1000),不带时间单位的形式,将使用查询库的时间精度作为默认时间单位,当存在多个库时默认采用精度更高的库;
3. INTERVAL('1s', '500a') SLIDING('1s'),带时间单位的字符串形式,字符串内部不能有任何空格等其它字符。
示例 SQL 如下:
```sql
SELECT tbname, _wstart, _wend, avg(voltage)
@ -220,7 +221,7 @@ Query OK, 12 row(s) in set (0.021265s)
#### 滑动窗口
每次执行的查询是一个时间窗口时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口time window 大小和每次前向增量时间forward sliding times。如下图[t0s t0e] [t1s t1e] [t2s t2e] 是分别是执行三次连续查询的时间窗口范围,窗口的前向滑动的时间范围 sliding time 标识 。查询过滤、聚合等操作按照每个时间窗口为独立的单位执行。
每次执行的查询是一个时间窗口时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口time window 大小和每次前向增量时间forward sliding times。如下图[t0s, t0e]、[t1s, t1e]、[t2s, t2e] 是分别是执行三次连续查询的时间窗口范围,窗口的前向滑动的时间范围 sliding time 标识。查询过滤、聚合等操作按照每个时间窗口为独立的单位执行。
![时间窗口示意图](./sliding-window.png)
@ -238,7 +239,7 @@ SELECT COUNT(*) FROM temp_tb_1 INTERVAL(1m) SLIDING(2m);
**使用时间窗口需要注意**
1. 聚合时间段的窗口宽度由关键词 INTERVAL 指定,最短时间间隔 10 毫秒10a并且支持偏移 offset偏移必须小于间隔也即时间窗口划分与“UTC 时刻 0”相比的偏移量。SLIDING 语句用于指定聚合时间段的前向增量,也即每次窗口向前滑动的时长。
2. 使用 INTERVAL 语句时,除非极特殊的情况,都要求把客户端和服务端的 taos.cfg 配置文件中的 timezone 参数配置为相同的取值,以避免时间处理函数频繁进行跨时区转换而导致的严重性能影响。
2. 使用 INTERVAL 语句时,除非极特殊的情况,都要求把客户端和服务端的 timezone 参数配置为相同的取值,以避免时间处理函数频繁进行跨时区转换而导致的严重性能影响。
3. 返回的结果中时间序列严格单调递增。
示例:
@ -274,7 +275,7 @@ Query OK, 11 row(s) in set (0.013153s)
#### 翻转窗口
当 SLIDING 与 INTERVAL 相等的时候,滑动窗口即为翻转窗口。翻转窗口和滑动窗口的区别在于,滑动窗口因为 interval_val 和 sliding_val 不同,不同时间窗口之间,会存在数据重叠,翻转窗口则没有数据重叠。本质上,翻转窗口就是按照 interval_val 进行了时间窗口划分INTERVAL(1m)和INTERVAL(1m) SLIDING(1m)是等效的。
当 SLIDING 与 INTERVAL 相等的时候,滑动窗口即为翻转窗口。翻转窗口和滑动窗口的区别在于,滑动窗口因为 interval_val 和 sliding_val 不同,不同时间窗口之间,会存在数据重叠,翻转窗口则没有数据重叠。本质上,翻转窗口就是按照 interval_val 进行了时间窗口划分INTERVAL(1m) INTERVAL(1m) SLIDING(1m) 是等效的。
示例:
@ -304,7 +305,7 @@ Query OK, 5 row(s) in set (0.016812s)
#### FILL 子句
1. 不进行填充NONE默认填充模式
2. VALUE 填充固定值填充此时需要指定填充的数值。例如FILL(VALUE, 1.23)。这里需要注意,最终填充的值受由相应列的类型决定,如 FILL(VALUE, 1.23),相应列为 INT 类型,则填充值为 1, 若查询列表中有多列需要 FILL, 则需要给每一个 FILL 列指定 VALUE, 如 `SELECT _wstart, min(c1), max(c1) FROM ... FILL(VALUE, 0, 0)`, 注意, SELECT 表达式中只有包含普通列时才需要指定 FILL VALUE, 如 `_wstart`, `_wstart+1a`, `now`, `1+1` 以及使用 partition by 时的 partition key (如 tbname)都不需要指定 VALUE, `timediff(last(ts), _wstart)` 则需要指定VALUE。
2. VALUE 填充固定值填充此时需要指定填充的数值。例如FILL(VALUE, 1.23)。这里需要注意,最终填充的值受由相应列的类型决定,如 FILL(VALUE, 1.23),相应列为 INT 类型,则填充值为 1,若查询列表中有多列需要 FILL则需要给每一个 FILL 列指定 VALUE`SELECT _wstart, min(c1), max(c1) FROM ... FILL(VALUE, 0, 0)`。注意SELECT 表达式中只有包含普通列时才需要指定 FILL VALUE`_wstart`、`_wstart+1a`、`now`、`1+1` 以及使用 partition by 时的 partition key (如 tbname)都不需要指定 VALUE,`timediff(last(ts), _wstart)` 则需要指定VALUE。
3. PREV 填充:使用前一个非 NULL 值填充数据。例如FILL(PREV)。
4. NULL 填充:使用 NULL 填充数据。例如FILL(NULL)。
5. LINEAR 填充:根据前后距离最近的非 NULL 值做线性插值填充。例如FILL(LINEAR)。
@ -313,11 +314,11 @@ Query OK, 5 row(s) in set (0.016812s)
以上填充模式中,除了 NONE 模式默认不填充值之外,其他模式在查询的整个时间范围内如果没有数据 FILL 子句将被忽略即不产生填充数据查询结果为空。这种行为在部分模式PREV、NEXT、LINEAR下具有合理性因为在这些模式下没有数据意味着无法产生填充数值。
对另外一些模式NULL、VALUE来说理论上是可以产生填充数值的至于需不需要输出填充数值取决于应用的需求。所以为了满足这类需要强制填充数据或 NULL 的应用的需求同时不破坏现有填充模式的行为兼容性TDengine 还支持两种新的填充模式:
1. NULL_F: 强制填充 NULL 值
2. VALUE_F: 强制填充 VALUE 值
1. NULL_F强制填充 NULL 值
2. VALUE_F强制填充 VALUE 值
NULL、 NULL_F、 VALUE、 VALUE_F 这几种填充模式针对不同场景区别如下:
1. INTERVAL 子句: NULL_F VALUE_F 为强制填充模式NULL VALUE 为非强制模式。在这种模式下下各自的语义与名称相符
NULL、NULL_F、VALUE、VALUE_F 这几种填充模式针对不同场景区别如下:
1. INTERVAL 子句:NULL_F、VALUE_F 为强制填充模式NULL、VALUE 为非强制模式。在这种模式下下各自的语义与名称相符
2. 流计算中的 INTERVAL 子句NULL_F 与 NULL 行为相同均为非强制模式VALUE_F 与 VALUE 行为相同,均为非强制模式。即流计算中的 INTERVAL 没有强制模式
3. INTERP 子句NULL 与 NULL_F 行为相同均为强制模式VALUE 与 VALUE_F 行为相同,均为强制模式。即 INTERP 中没有非强制模式。
@ -405,7 +406,7 @@ Query OK, 22 row(s) in set (0.153403s)
### 会话窗口
会话窗口根据记录的时间戳主键的值来确定是否属于同一个会话。如下图所示,如果设置时间戳的连续的间隔小于等于 12 秒,则以下 6 条记录构成 2 个会话窗口,分别是:[2019-04-28 14:22:102019-04-28 14:22:30]和[2019-04-28 14:23:102019-04-28 14:23:30]。因为 2019-04-28 14:22:30 与 2019-04-28 14:23:10 之间的时间间隔是 40 秒超过了连续时间间隔12 秒)。
会话窗口根据记录的时间戳主键的值来确定是否属于同一个会话。如下图所示,如果设置时间戳的连续的间隔小于等于 12 秒,则以下 6 条记录构成 2 个会话窗口,分别是:[2019-04-28 14:22:102019-04-28 14:22:30] [2019-04-28 14:23:102019-04-28 14:23:30]。因为 2019-04-28 14:22:30 与 2019-04-28 14:23:10 之间的时间间隔是 40 秒超过了连续时间间隔12 秒)。
![会话窗口示意图](./session-window.png)
@ -452,7 +453,7 @@ Query OK, 10 row(s) in set (0.043489s)
事件窗口无法关闭时,不构成一个窗口,不会被输出。即有数据满足 start_trigger_condition此时窗口打开但后续数据都不能满足 end_trigger_condition这个窗口无法被关闭这部分数据不够成一个窗口不会被输出。
如果直接在超级表上进行事件窗口查询TDengine 会将超级表的数据汇总成一条时间线,然后进行事件窗口的计算。 如果需要对子查询的结果集进行事件窗口查询,那么子查询的结果集需要满足按时间线输出的要求,且可以输出有效的时间戳列。
如果直接在超级表上进行事件窗口查询TDengine 会将超级表的数据汇总成一条时间线,然后进行事件窗口的计算。如果需要对子查询的结果集进行事件窗口查询,那么子查询的结果集需要满足按时间线输出的要求,且可以输出有效的时间戳列。
以下面的 SQL 语句为例,事件窗口切分如下图所示。
@ -474,7 +475,7 @@ EVENT_WINDOW START WITH voltage >= 225 END WITH voltage < 235
LIMIT 5;
```
上面的 SQL查询超级表meters中时间戳大于等于2022-01-01T00:00:00+08:00且时间戳小于2022-01-01T00:10:00+08:00的数据数据先按照子表名tbname进行数据切分再根据事件窗口条件电压大于等于 225V且小于 235V 进行切分;最后,取每个分片的前 5 行的数据作为结果,返回子表名、窗口开始时间、窗口结束时间、窗口宽度、窗口内数据条数。查询结果如下:
上面的 SQL查询超级表 meters 中,时间戳大于等于 2022-01-01T00:00:00+08:00且时间戳小于 2022-01-01T00:10:00+08:00 的数据;数据先按照子表名 tbname 进行数据切分,再根据事件窗口条件:电压大于等于 225V且小于 235V 进行切分;最后,取每个分片的前 5 行的数据作为结果,返回子表名、窗口开始时间、窗口结束时间、窗口宽度、窗口内数据条数。查询结果如下:
```text
tbname | _wstart | _wend | _wduration | count(*) |
@ -529,25 +530,25 @@ Query OK, 10 row(s) in set (0.062794s)
时序数据特有函数是 TDengine 针对时序数据查询场景专门设计的一组函数。在通用数据库中要实现类似的功能通常需要编写复杂的查询语句而且效率较低。为了降低用户的使用成本和简化查询过程TDengine 将这些功能以内置函数的形式提供,从而实现了高效且易于使用的时序数据处理能力。时序数据特有函数如下表所示。
| 函数 | 功能说明 |
|:---------------:|:--------------------------------------------------------------------:|
|CSUM | 累加和Cumulative sum忽略 NULL 值。 |
|DERIVATIVE | 统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒1signore_negative 参数的值可以是 0 或 1为 1 时表示忽略负值。 |
|DIFF | 统计表中某列的值与前一行对应值的差。 ignore_negative 取值为 0|1 可以不填,默认值为 0。 不忽略负值。ignore_negative 为 1 时表示忽略负数。|
|IRATE | 计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。 |
|MAVG | 计算连续 k 个值的移动平均数moving average。如果输入行数小于 k则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。|
|STATECOUNT | 返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1条件为 false 则重置为 -1如果数据为 NULL跳过该条数据。 |
| 函数 | 功能说明 |
|:------------:|:--------------------------------------------------------------------:|
|CSUM | 累加和Cumulative sum忽略 NULL 值。|
|DERIVATIVE | 统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒1signore_negative 参数的值可以是 0 或 1为 1 时表示忽略负值。|
|DIFF | 统计表中某列的值与前一行对应值的差。ignore_negative 取值为 0|1 ,可以不填,默认值为 0。不忽略负值。ignore_negative 为 1 时表示忽略负数。|
|IRATE | 计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。|
|MAVG | 计算连续 k 个值的移动平均数moving average。如果输入行数小于 k则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。|
|STATECOUNT | 返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1条件为 false 则重置为 -1如果数据为 NULL跳过该条数据。|
|STATEDURATION | 返回满足某个条件的连续记录的时间长度,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加上两个记录之间的时间长度(第一个满足条件的记录时间长度记为 0条件为 false 则重置为 -1如果数据为 NULL跳过该条数据|
|TWA | 时间加权平均函数。统计表中某列在一段时间内的时间加权平均。 |
|TWA | 时间加权平均函数。统计表中某列在一段时间内的时间加权平均。|
## 嵌套查询
嵌套查询,也称为 subquery子查询是指在一个 SQL 中内层查询的计算结果可以作为外层查询的计算对象来使用。TDengine 支持在 from 子句中使用非关联 subquery。非关联是指 subquery 不会用到父查询中的参数。在 select 查询的 from 子句之后,可以接一个独立的 select 语句,这个 select 语句被包含在英文圆括号内。通过使用嵌套查询你可以在一个查询中引用另一个查询的结果从而实现更复杂的数据处理和分析。以智能电表为例进行说明SQL 如下
```sql
SELECT max(voltage),*
SELECT max(voltage), *
FROM (
SELECT tbname,last_row(ts),voltage,current,phase,groupid,location
SELECT tbname, last_row(ts), voltage, current, phase, groupid, location
FROM meters
PARTITION BY tbname
)
@ -559,12 +560,12 @@ GROUP BY groupid;
TDengine 的嵌套查询遵循以下规则:
1. 内层查询的返回结果将作为“虚拟表”供外层查询使用,此虚拟表建议起别名,以便于外层查询中方便引用。
2. 外层查询支持直接通过列名或列名的形式引用内层查询的列或伪列。
3. 在内层和外层查询中,都支持普通表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。
3. 在内层和外层查询中,都支持普通表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。
4. 内层查询支持的功能特性与非嵌套的查询语句能力是一致的。内层查询的 ORDER BY 子句一般没有意义,建议避免这样的写法以免无谓的资源消耗。
5. 与非嵌套的查询语句相比,外层查询所能支持的功能特性存在如下限制:
6. 如果内层查询的结果数据未提供时间戳那么计算过程隐式依赖时间戳的函数在外层会无法正常工作。例如INTERP DERIVATIVE IRATE LAST_ROW FIRST LAST TWA STATEDURATION TAIL UNIQUE。
7. 如果内层查询的结果数据不是按时间戳有序那么计算过程依赖数据按时间有序的函数在外层会无法正常工作。例如LEASTSQUARES ELAPSED INTERP DERIVATIVE IRATE TWA DIFF STATECOUNT STATEDURATION CSUM MAVG TAIL UNIQUE。
8. 计算过程需要两遍扫描的函数,在外层查询中无法正常工作。例如:此类函数包括:PERCENTILE。
6. 如果内层查询的结果数据未提供时间戳那么计算过程隐式依赖时间戳的函数在外层会无法正常工作。例如INTERP、DERIVATIVE、IRATE、LAST_ROW、FIRST、LAST、TWA、STATEDURATION、TAIL、UNIQUE。
7. 如果内层查询的结果数据不是按时间戳有序那么计算过程依赖数据按时间有序的函数在外层会无法正常工作。例如LEASTSQUARES、ELAPSED、INTERP、DERIVATIVE、IRATE、TWA、DIFF、STATECOUNT、STATEDURATION、CSUM、MAVG、TAIL、UNIQUE。
8. 计算过程需要两遍扫描的函数在外层查询中无法正常工作。例如PERCENTILE。
## UNION 子句
@ -573,11 +574,11 @@ TDengine 支持 UNION 操作符。也就是说,如果多个 SELECT 子句返
示例:
```sql
(SELECT tbname,* FROM d1 limit 1)
(SELECT tbname, * FROM d1 limit 1)
UNION ALL
(SELECT tbname,* FROM d11 limit 2)
(SELECT tbname, * FROM d11 limit 2)
UNION ALL
(SELECT tbname,* FROM d21 limit 3);
(SELECT tbname, * FROM d21 limit 3);
```
上面的 SQL分别查询子表 d1 的 1 条数据,子表 d11 的 2 条数据,子表 d21 的 3 条数据,并将结果合并。返回的结果如下:
@ -594,7 +595,7 @@ UNION ALL
Query OK, 6 row(s) in set (0.006438s)
```
在同一个 sql 语句中,最多支持 100 个 UNION 子句。
在同一个 SQL 语句中,最多支持 100 个 UNION 子句。
## 关联查询
@ -640,9 +641,9 @@ select a.* from meters a left asof join meters b on timetruncate(a.ts, 1s) < tim
### 语法说明
在接下来的内容中,我们将通过统一的方式并行介绍 Left Join 和 Right Join 系列。因此,在后续关于 Outer、Semi、Anti-Semi、ASOF、Window 等系列内容的介绍中,我们采用了“ Left/Right”这种表述方式来同时涵盖 Left Join 和 Right Join 的相关知识。这里的“ /”符号前的描述专指应用于 Left Join而“ /”符号后的描述则专指应用于 Right Join。通过这种表述方式我们可以更加清晰地展示这两种 Join 操作的特点和用法。
在接下来的内容中,我们将通过统一的方式并行介绍 Left Join 和 Right Join 系列。因此,在后续关于 Outer、Semi、Anti-Semi、ASOF、Window 等系列内容的介绍中我们采用了“Left/Right”这种表述方式来同时涵盖 Left Join 和 Right Join 的相关知识。这里的“/”符号前的描述专指应用于 Left Join而“/”符号后的描述则专指应用于 Right Join。通过这种表述方式我们可以更加清晰地展示这两种 Join 操作的特点和用法。
例如,当我们提及“左 / 右表”时,对于 Left Join它特指左表而对于 Right Join它则特指右表。同理当我们提及“右 / 左表”时,对于 Left Join它特指右表而对于 Right Join它则特指左表。
例如,当我们提及“左/右表”时,对于 Left Join它特指左表而对于 Right Join它则特指右表。同理当我们提及“右/左表”时,对于 Left Join它特指右表而对于 Right Join它则特指左表。
### Join 功能
@ -650,13 +651,13 @@ select a.* from meters a left asof join meters b on timetruncate(a.ts, 1s) < tim
| Join 类型 | 定义 |
|:------------------------:|:--------------------------------------------------------:|
|Inner Join | 内连接,只有左右表中同时符合连接条件的数据才会被返回,可以视为两张表符合连接条件的数据的交集 |
|Left/Right Outer Join | 左 / 右(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左 / 右表中不符合连接条件的数据集合 |
|Left/Right Semi Join | 左 / 右半连接,通常表达的是 in、exists 的含义,即对左 / 右表任意一条数据来说,只有当右 / 左表中存在任一符合连接条件的数据时才返回左 / 右表行数据 |
|Inner Join | 内连接,只有左右表中同时符合连接条件的数据才会被返回,可以视为两张表符合连接条件的数据的交集 |
|Left/Right Outer Join | 左 / 右(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左 / 右表中不符合连接条件的数据集合 |
|Left/Right Semi Join | 左 / 右半连接,通常表达的是 in、exists 的含义,即对左 / 右表任意一条数据来说,只有当右 / 左表中存在任一符合连接条件的数据时才返回左 / 右表行数据 |
|Left/Right Anti-Semi Join | 左 / 右反连接,同左 / 右半连接的逻辑正好相反,通常表达的是 not in、not exists 的含义,即对左 / 右表任意一条数据来说,只有当右 / 左表中不存在任何符合连接条件的数据时才返回左 / 右表行数据 |
|left/Right ASOF Join | 左 / 右不完全匹配连接,不同于其他传统 Join 操作的完全匹配模式ASOF Join 允许以指定的匹配模式进行不完全匹配,即按照主键时间戳最接近的方式进行匹配 |
|Left/Right Window Join | 左 / 右窗口连接,根据左 / 右表中每一行的主键时间戳和窗口边界构造窗口并据此进行窗口连接,支持在窗口内进行投影、标量和聚合操作 |
|Full Outer Join | 全(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左右表中不符合连接条件的数据集合 |
|left/Right ASOF Join | 左 / 右不完全匹配连接,不同于其他传统 Join 操作的完全匹配模式ASOF Join 允许以指定的匹配模式进行不完全匹配,即按照主键时间戳最接近的方式进行匹配 |
|Left/Right Window Join | 左 / 右窗口连接,根据左 / 右表中每一行的主键时间戳和窗口边界构造窗口并据此进行窗口连接,支持在窗口内进行投影、标量和聚合操作 |
|Full Outer Join | 全(外)连接,既包含左右表中同时符合连接条件的数据集合,也包括左右表中不符合连接条件的数据集合 |
### 约束和限制

View File

@ -12,7 +12,7 @@ toc_max_heading_level: 4
为实现上述功能TDengine 会为预写数据日志Write-Ahead LoggingWAL文件自动创建索引以支持快速随机访问并提供了灵活可配置的文件切换与保留机制。用户可以根据需求指定 WAL 文件的保留时间和大小。通过这些方法WAL 被改造成一个保留事件到达顺序的、可持久化的存储引擎。对于以主题形式创建的查询TDengine 将从 WAL 读取数据。在消费过程中TDengine 根据当前消费进度从 WAL 直接读取数据,并使用统一的查询引擎实现过滤、变换等操作,然后将数据推送给消费者。
从 3.2.0.0 版本开始,数据订阅支持 vnode 迁移和分裂。 由于数据订阅依赖 wal文件而在 vnode 迁移和分裂的过程中wal 并不会同步过去,所以迁移或分裂后,之前没消费完的 wal数据后消费不到。所以请保证之前把数据全部消费完后再进行 vnode 迁移或分裂,否则,消费会丢失数据
从 3.2.0.0 版本开始,数据订阅支持 vnode 迁移和分裂。由于数据订阅依赖 wal 文件,而在 vnode 迁移和分裂的过程中wal 文件并不会进行同步。因此,在迁移或分裂操作完成后,您将无法继续消费之前尚未消费完 wal 数据。请务必在执行 vnode 迁移或分裂之前,将所有 wal 数据消费完毕
## 主题类型
@ -31,7 +31,7 @@ CREATE TOPIC [IF NOT EXISTS] topic_name as subquery
3. 若发生表结构变更,新增的列不出现在结果中。
4. 对于 select *,则订阅展开为创建时所有的列(子表、普通表为数据列,超级表为数据列加标签列)
假设需要订阅所有智能电表中电压值大于 200 的数据,且仅仅返回时间戳、电流、电压 3 个采集量(不返回相位),那么可以通过下面的 SQL 创建 power_topic 这个主题。
假设需要订阅所有智能电表中电压值大于 200 的数据,且仅仅返回时间戳、电流、电压 3 个采集量(不返回相位),那么可以通过下面的 SQL 创建 power_topic 这个主题。
```sql
CREATE TOPIC power_topic AS SELECT ts, current, voltage FROM power.meters WHERE voltage > 200;
```
@ -45,21 +45,21 @@ CREATE TOPIC [IF NOT EXISTS] topic_name [with meta] AS STABLE stb_name [where_co
与使用 `SELECT * from stbName` 订阅的区别是:
1. 不会限制用户的表结构变更,即表结构变更以及变更后的新数据都能够订阅到
1. 不会限制用户的表结构变更,即表结构变更以及变更后的新数据都能够订阅到
2. 返回的是非结构化的数据,返回数据的结构会随着超级表的表结构变化而变化。
3. with meta 参数可选,选择时将返回创建超级表,子表等语句,主要用于 taosx 做超级表迁移。
4. where_condition 参数可选选择时将用来过滤符合条件的子表订阅这些子表。where 条件里不能有普通列,只能是 tag 或 tbnamewhere 条件里可以用函数,用来过滤 tag但是不能是聚合函数因为子表 tag 值无法做聚合。可以是常量表达式,比如 2 > 1订阅全部子表或者 false订阅 0 个子表)。
3. with meta 参数可选,选择时将返回创建超级表,子表等语句,主要用于 taosX 做超级表迁移。
4. where_condition 参数可选选择时将用来过滤符合条件的子表订阅这些子表。where 条件里不能有普通列,只能是 tag 或 tbnamewhere 条件里可以用函数,用来过滤 tag但是不能是聚合函数因为子表 tag 值无法做聚合。可以是常量表达式,比如 2 > 1订阅全部子表或者 false订阅 0 个子表)。
5. 返回数据不包含标签。
### 数据库主题
订阅一个数据库里所有数据,其语法如下
订阅一个数据库里所有数据,其语法如下
```sql
CREATE TOPIC [IF NOT EXISTS] topic_name [with meta] AS DATABASE db_name;
```
通过该语句可创建一个包含数据库所有表数据的订阅
1. with meta 参数可选,选择时将返回数据库里所有超级表,子表、普通表的元数据创建、删除、修改语句,主要用于 taosx 做数据库迁移。
通过该语句可创建一个包含数据库所有表数据的订阅
1. with meta 参数可选,选择时将返回数据库里所有超级表,子表、普通表的元数据创建、删除、修改语句,主要用于 taosX 做数据库迁移。
2. 超级表订阅和库订阅属于高级订阅模式,容易出错,如确实要使用,请咨询技术支持人员。
## 删除主题
@ -128,7 +128,7 @@ TDengine 的数据订阅功能支持回放replay功能允许用户按
2023/09/22 00:00:08.000
```
使用数据订阅的回放功能时需要注意如下几项
使用数据订阅的回放功能时需要注意如下几项
- 数据订阅的回放功能仅查询订阅支持数据回放,超级表和库订阅不支持回放。
- 回放不支持进度保存。
- 因为数据回放本身需要处理时间,所以回放的精度存在几十毫秒的误差。

View File

@ -29,14 +29,14 @@ TDengine 采用时间驱动的缓存管理策略,将最新数据优先存储
## TDengine 的读缓存配置
在创建数据库时,用户可以选择是否启用缓存机制以存储该数据库中每张子表的最新数据。这一缓存机制由数据库创建参数 cachemodel 进行控制。参数 cachemodel 具有如 下 4 种情况:
在创建数据库时,用户可以选择是否启用缓存机制以存储该数据库中每张子表的最新数据。这一缓存机制由数据库创建参数 cachemodel 进行控制。参数 cachemodel 具有如下 4 种情况:
- none不缓存
- last_row缓存子表最近一行数据这将显著改善 last_row 函数的性能
- last_value缓存子表每一列最近的非 NULL 值,这将显著改善无特殊影响(比如 WHERE,ORDER BY,GROUP BY, INTERVAL时的 last 函数的性能
- last_value缓存子表每一列最近的非 NULL 值,这将显著改善无特殊影响(比如 WHERE、ORDER BY、GROUP BY、INTERVAL时的 last 函数的性能
- both同时缓存最近的行和列即等同于上述 cachemodel 值为 last_row 和 last_value 的行为同时生效
当使用数据库读缓存时,可以使用参数 cachesize 来配置每个 vnode 的内存大小。
- cachesize表示每个 vnode 中用于缓存子表最近数据的内存大小。默认为 1 ,范围是[165536],单位是 MB。需要根据机器内存合理配置。
- cachesize表示每个 vnode 中用于缓存子表最近数据的内存大小。默认为 1范围是 [165536],单位是 MB。需要根据机器内存合理配置。
关于数据库的具体创建,相关参数和操作说明请参考[创建数据库](../../reference/taos-sql/database/)
@ -48,25 +48,25 @@ TDengine 采用时间驱动的缓存管理策略,将最新数据优先存储
# taosBenchmark -d power -Q --start-timestamp=1600000000000 --tables=10000 --records=10000 --time-step=10000 -y
```
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的 电表数据库 power产生共 10 亿条时序数据。时序数据的时间戳从 `16000000000002020-09-13T20:26:40+08:00`开始,超级表为 `meter`s,包含 10000 个设备(子表),每个设备有 10000 条数据,时序数据的采集频率是 10 秒/ 条。
上面的命令taosBenchmark 工具在 TDengine 中生成了一个用于测试的 电表数据库 power产生共 10 亿条时序数据。时序数据的时间戳从 `16000000000002020-09-13T20:26:40+08:00` 开始,超级表为 `meters`,包含 10000 个设备(子表),每个设备有 10000 条数据,时序数据的采集频率是 10 秒/条。
查询任意一个电表的最新的电流和时间戳数据,执行如下 SQL
```sql
taos> select last(ts,current) from meters;
taos> select last(ts, current) from meters;
last(ts) | last(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.353815s)
taos> select last_row(ts,current) from meters;
taos> select last_row(ts, current) from meters;
last_row(ts) | last_row(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.344070s)
```
希望使用缓存来查询任意一个电表的最新时间戳数据,执行如下 SQL ,并检查数据库的缓存生效。
希望使用缓存来查询任意一个电表的最新时间戳数据,执行如下 SQL并检查数据库的缓存生效。
```sql
taos> alter database power cachemodel 'both' ;
@ -82,13 +82,13 @@ Query OK, 1 row(s) in set (0.000282s)
再次查询电表的最新的实时数据,第一次查询会做缓存计算,后续的查询时延就大大缩减。
```sql
taos> select last(ts,current) from meters;
taos> select last(ts, current) from meters;
last(ts) | last(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |
Query OK, 1 row(s) in set (0.044021s)
taos> select last_row(ts,current) from meters;
taos> select last_row(ts, current) from meters;
last_row(ts) | last_row(current) |
=================================================
2020-09-15 00:13:10.000 | 1.1294620 |

View File

@ -60,20 +60,20 @@ subquery 支持会话窗口、状态窗口、时间窗口、事件窗口与计
3. INTERVAL 是时间窗口又可分为滑动时间窗口和翻转时间窗口。INTERVAL 子句用于指定窗口相等时间周期SLIDING 字句用于指定窗口向前滑动的时间。当 interval_val 与 sliding_val 相等的时候时间窗口即为翻转时间窗口否则为滑动时间窗口注意sliding_val 必须小于等于 interval_val。
4. EVENT_WINDOW 是事件窗口,根据开始条件和结束条件来划定窗口。当 start_trigger_condition 满足时则窗口开始,直到 end_trigger_condition 满足时窗口关闭。 start_trigger_condition 和 end_trigger_condition 可以是任意 TDengine 支持的条件表达式,且可以包含不同的列。
4. EVENT_WINDOW 是事件窗口,根据开始条件和结束条件来划定窗口。当 start_trigger_condition 满足时则窗口开始,直到 end_trigger_condition 满足时窗口关闭。start_trigger_condition 和 end_trigger_condition 可以是任意 TDengine 支持的条件表达式,且可以包含不同的列。
5. COUNT_WINDOW 是计数窗口,按固定的数据行数来划分窗口。 count_val 是常量,是正整数,必须大于等于 2小于 2147483648。 count_val 表示每个 COUNT_WINDOW 包含的最大数据行数,总数据行数不能整除 count_val 时,最后一个窗口的行数会小于 count_val sliding_val 是常量,表示窗口滑动的数量,类似于 INTERVAL 的 SLIDING 。
5. COUNT_WINDOW 是计数窗口按固定的数据行数来划分窗口。count_val 是常量,是正整数,必须大于等于 2小于 2147483648。count_val 表示每个 COUNT_WINDOW 包含的最大数据行数,总数据行数不能整除 count_val 时,最后一个窗口的行数会小于 count_val。sliding_val 是常量,表示窗口滑动的数量,类似于 INTERVAL 的 SLIDING 。
窗口的定义与时序数据窗口查询中的定义完全相同,具体可参考 TDengine 窗口函数部分。
如下 SQL 将创建一个流计算,执行后 TDengine 会自动创建名为avg_vol 的超级表,此流计算以 1min 为时间窗口、30s 为前向增量统计这些智能电表的平均电压,并将来自 meters 的数据的计算结果写入 avg_vol不同分区的数据会分别创建子表并写入不同子表。
如下 SQL 将创建一个流计算,执行后 TDengine 会自动创建名为 avg_vol 的超级表,此流计算以 1min 为时间窗口、30s 为前向增量统计这些智能电表的平均电压,并将来自 meters 的数据的计算结果写入 avg_vol不同分区的数据会分别创建子表并写入不同子表。
```sql
CREATE STREAM avg_vol_s INTO avg_vol AS
SELECT _wstart, count(*), avg(voltage) FROM power.meters PARTITION BY tbname INTERVAL(1m) SLIDING(30s);
```
本节涉及的相关参数的说明如下。
- stb_name 是保存计算结果的超级表的表名,如果该超级表不存在,则会自动创建;如果已存在,则检查列的 schema 信息。详见 6.3.8 节。
- stb_name 是保存计算结果的超级表的表名,如果该超级表不存在,则会自动创建;如果已存在,则检查列的 schema 信息。
- tags 子句定义了流计算中创建标签的规则。通过 tags 字段可以为每个分区对应的子表生成自定义的标签值。
## 流式计算的规则和策略

View File

@ -20,7 +20,7 @@ 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 还可以直接调用 taosadapter 提供的 REST API 接口,进行数据写入和查询操作。
TDengine 提供了丰富的应用程序开发接口为了便于用户快速开发自己的应用TDengine 支持了多种编程语言的连接器,其中官方连接器包括支持 C/C++、Java、Python、Go、Node.js、C#、Rust、Lua社区贡献和 PHP 社区贡献的连接器。这些连接器支持使用原生接口taosc和 REST 接口(部分语言暂不支持)连接 TDengine 集群。社区开发者也贡献了多个非官方连接器,例如 ADO.NET 连接器、Lua 连接器和 PHP 连接器。另外 TDengine 还可以直接调用 taosAdapter 提供的 REST API 接口,进行数据写入和查询操作。
## 连接方式
@ -33,7 +33,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
![TDengine connection type](connection-type-zh.webp)
无论使用何种方式建立连接,连接器都提供了相同或相似的 API 操作数据库,都可以执行 SQL 语句,只是初始化连接的方式稍有不同,用户在使用上不会感到什么差别。
各种连接方式和各语言连接器支持情况请参考[连接器功能特性](../../reference/connector/#功能特性)
各种连接方式和各语言连接器支持情况请参考 [连接器功能特性](../../reference/connector/#功能特性)
关键不同点在于:

View File

@ -5,19 +5,19 @@ description: 让开发者能够快速上手的指南
开发一个应用,如果你准备采用 TDengine 作为时序数据处理的工具,那么有如下几个事情要做:
1. 确定应用到 TDengine 的连接方式。无论你使用何种编程语言,你总是可以使用 REST 接口, 但也可以使用每种编程语言独有的连接器进行方便的连接。
1. 确定应用到 TDengine 的连接方式。无论你使用何种编程语言,你总是可以使用 REST 接口但也可以使用每种编程语言独有的连接器进行方便的连接。
2. 根据自己的应用场景,确定数据模型。根据数据特征,决定建立一个还是多个库;分清静态标签、采集量,建立正确的超级表,建立子表。
3. 决定插入数据的方式。TDengine 支持使用标准的 SQL 写入,但同时也支持 Schemaless 模式写入,这样不用手工建表,可以将数据直接写入。
4. 根据业务要求,看需要撰写哪些 SQL 查询语句。
5. 如果你要基于时序数据做轻量级的实时统计分析,包括各种监测看板,那么建议你采用 TDengine 3.0 的流式计算功能,而不用额外部署 Spark, Flink 等复杂的流式计算系统。
5. 如果你要基于时序数据做轻量级的实时统计分析,包括各种监测看板,那么建议你采用 TDengine 3.0 的流式计算功能,而不用额外部署 SparkFlink 等复杂的流式计算系统。
6. 如果你的应用有模块需要消费插入的数据,希望有新的数据插入时,就能获取通知,那么建议你采用 TDengine 提供的数据订阅功能,而无需专门部署 Kafka 或其他消息队列软件。
7. 在很多场景下(如车辆管理),应用需要获取每个数据采集点的最新状态,那么建议你采用 TDengine 的 Cache 功能,而不用单独部署 Redis 等缓存软件。
8. 如果你发现 TDengine 的函数无法满足你的要求那么你可以使用用户自定义函数UDF来解决问题。
本部分内容就是按照上述顺序组织的。为便于理解TDengine 为每个功能和每个支持的编程语言都提供了示例代码,位于 [示例代码](https://github.com/taosdata/TDengine/tree/main/docs/examples)。所有示例代码都会有 CI 保证正确性,脚本位于 [示例代码 CI](https://github.com/taosdata/TDengine/tree/main/tests/docs-examples-test)。
如果你希望深入了解 SQL 的使用,需要查看[SQL 手册](../reference/taos-sql/)。如果想更深入地了解各连接器的使用,请阅读[连接器参考指南](../reference/connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana, 请参考[第三方工具](../third-party/)。
如果你希望深入了解 SQL 的使用,需要查看 [SQL 手册](../reference/taos-sql/)。如果想更深入地了解各连接器的使用,请阅读 [连接器参考指南](../reference/connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana,请参考 [第三方工具](../third-party/)。
如果在开发过程中遇到任何问题,请点击每个页面下方的["反馈问题"](https://github.com/taosdata/TDengine/issues/new/choose), 在 GitHub 上直接递交 Issue。
如果在开发过程中遇到任何问题,请点击每个页面下方的 [反馈问题](https://github.com/taosdata/TDengine/issues/new/choose)在 GitHub 上直接递交 Issue。
```mdx-code-block
import DocCardList from '@theme/DocCardList';