doc: minor changes

This commit is contained in:
Shengliang Guan 2025-02-18 14:34:30 +08:00
parent 6f08e379d4
commit f23fc3328e
3 changed files with 76 additions and 75 deletions

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 将使用第一列时间戳建立索引,采用列式存储。对于复杂的设备,比如汽车,它有多个数据采集点,则需要为一辆汽车建立多张表。
@ -134,8 +134,8 @@ 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 后面的括号中,定义超级表的标签(标签名、数据类型等)。
1. 标签的数据类型可以为整型、浮点型、字符串等。例如:`location varchar(64)` 表示,标签地区 `location`,数据类型为 `varchar(64)`
@ -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 来指定或输出对应操作的子表名。

View File

@ -74,21 +74,21 @@ 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 | 统计指定字段的记录行数 |
|AVG | 统计指定字段的平均值|
|COUNT | 统计指定字段的记录行数|
|ELAPSED|elapsed 函数表达了统计周期内连续的时间长度,和 twa 函数配合使用可以计算统计曲线下的面积。在通过 INTERVAL 子句指定窗口的情况下,统计在给定时间范围内的每个窗口内有数据覆盖的时间范围;如果没有 INTERVAL 子句则返回整个给定时间范围内的有数据覆盖的时间范围。注意ELAPSED 返回的并不是时间范围的绝对值,而是绝对值除以 time_unit 所得到的单位个数。|
|LEASTSQUARES | 统计表中某列的值的拟合直线方程。start_val 是自变量初始值step_val 是自变量的步长值。|
|SPREAD | 统计表中某列的最大值和最小值之差。|
|STDDEV | 统计表中某列的均方差。|
|SUM | 统计表/超级表中某列的和。|
|HYPERLOGLOG | 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。在数据量较少的时候该算法不是很准确,可以使用 select countdata from select uniquecol as data from table 的方法。 |
|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 (年);
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. 返回的结果中时间序列严格单调递增。
示例:
@ -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 为非强制模式。在这种模式下下各自的语义与名称相符
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 中没有非强制模式。
@ -530,7 +531,7 @@ 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 时表示忽略负数。|
@ -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 子句
@ -594,7 +595,7 @@ UNION ALL
Query OK, 6 row(s) in set (0.006438s)
```
在同一个 sql 语句中,最多支持 100 个 UNION 子句。
在同一个 SQL 语句中,最多支持 100 个 UNION 子句。
## 关联查询