Merge pull request #29993 from taosdata/fix/marks/tmq_poll

fix: remove waitting for empty block & optimize poll logic
This commit is contained in:
Simon Guan 2025-03-05 14:21:40 +08:00
commit e69021e0f2
24 changed files with 442 additions and 329 deletions

View File

@ -537,8 +537,10 @@ This document details the server error codes that may be encountered when using
| Error Code | Description | Possible Error Scenarios or Reasons | Recommended Actions for Users | | Error Code | Description | Possible Error Scenarios or Reasons | Recommended Actions for Users |
| ---------- | --------------------- | ------------------------------------------------------------ | -------------------------------------------- | | ---------- | --------------------- | ------------------------------------------------------------ | -------------------------------------------- |
| 0x800003E6 | Consumer not exist | Consumer timeout offline | rebuild consumer to subscribe data again |
| 0x800003EA | Consumer not ready | Consumer rebalancing | retry after 2s |
| 0x80004000 | Invalid message | The subscribed data is illegal, generally does not occur | Check the client-side error logs for details | | 0x80004000 | Invalid message | The subscribed data is illegal, generally does not occur | Check the client-side error logs for details |
| 0x80004001 | Consumer mismatch | The vnode requested for subscription and the reassigned vnode are inconsistent, usually occurs when new consumers join the same consumer group | Internal error, not exposed to users | | 0x80004001 | Consumer mismatch | The vnode requested for subscription and the reassigned vnode are inconsistent, usually occurs when new consumers join the same consumer group | Internal error |
| 0x80004002 | Consumer closed | The consumer no longer exists | Check if it has already been closed | | 0x80004002 | Consumer closed | The consumer no longer exists | Check if it has already been closed |
| 0x80004017 | Invalid status, please subscribe topic first | tmq status invalidate | Without calling subscribe, directly poll data | | 0x80004017 | Invalid status, please subscribe topic first | tmq status invalidate | Without calling subscribe, directly poll data |
| 0x80004100 | Stream task not exist | The stream computing task does not exist | Check the server-side error logs | | 0x80004100 | Stream task not exist | The stream computing task does not exist | Check the server-side error logs |

View File

@ -36,8 +36,8 @@ TDengine 消费者的概念跟 Kafka 类似,消费者通过订阅主题来接
| `td.connect.port` | integer | 服务端的端口号 | | | `td.connect.port` | integer | 服务端的端口号 | |
| `group.id` | string | 消费组 ID同一消费组共享消费进度 | <br />**必填项**。最大长度192超长将截断。<br />每个topic最多可建立 100 个 consumer group | | `group.id` | string | 消费组 ID同一消费组共享消费进度 | <br />**必填项**。最大长度192超长将截断。<br />每个topic最多可建立 100 个 consumer group |
| `client.id` | string | 客户端 ID | 最大长度255超长将截断。 | | `client.id` | string | 客户端 ID | 最大长度255超长将截断。 |
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default(version < 3.2.0.0);从头开始订阅; <br/>`latest`: default(version >= 3.2.0.0);仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 | | `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`default(version < 3.2.0.0)从头开始订阅<br/>`latest`default(version >= 3.2.0.0);仅从最新数据开始订阅;<br/>`none`没有提交的 offset 无法订阅 |
| `enable.auto.commit` | boolean | 是否启用消费位点自动提交true: 自动提交客户端应用无需commitfalse客户端应用需要自行commit | 默认值为 true | | `enable.auto.commit` | boolean | 是否启用消费位点自动提交true自动提交客户端应用无需commitfalse客户端应用需要自行 commit | 默认值为 true |
| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 | | `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 |
| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句)(从 3.2.0.0 版本该参数废弃,恒为 true | 默认关闭 | | `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句)(从 3.2.0.0 版本该参数废弃,恒为 true | 默认关闭 |
| `enable.replay` | boolean | 是否开启数据回放功能 | 默认关闭 | | `enable.replay` | boolean | 是否开启数据回放功能 | 默认关闭 |

View File

@ -57,7 +57,7 @@ LIKE 条件使用通配符字符串进行匹配检查,规则如下:
MATCH/REGEXP 条件和 NMATCH/NOT REGEXP 条件使用正则表达式进行匹配,规则如下: MATCH/REGEXP 条件和 NMATCH/NOT REGEXP 条件使用正则表达式进行匹配,规则如下:
- 支持符合 POSIX 规范的正则表达式,具体规范内容可参见 Regular Expressions。 - 支持符合 POSIX 规范的正则表达式,具体规范内容可参见 Regular Expressions。
- MATCH 和正则表达式匹配时, 返回 TURE. NMATCH 和正则表达式不匹配时, 返回 TRUE. - MATCH 和正则表达式匹配时,返回 TURE。NMATCH 和正则表达式不匹配时,返回 TRUE.
- 只能针对子表名(即 tbname、字符串类型的标签值进行正则表达式过滤不支持普通列的过滤。 - 只能针对子表名(即 tbname、字符串类型的标签值进行正则表达式过滤不支持普通列的过滤。
- 正则匹配字符串长度不能超过 128 字节。可以通过参数 maxRegexStringLen 设置和调整最大允许的正则匹配字符串,该参数是客户端配置参数,需要重启客户端才能生效 - 正则匹配字符串长度不能超过 128 字节。可以通过参数 maxRegexStringLen 设置和调整最大允许的正则匹配字符串,该参数是客户端配置参数,需要重启客户端才能生效
@ -65,7 +65,7 @@ MATCH/REGEXP 条件和 NMATCH/NOT REGEXP 条件使用正则表达式进行匹配
| # | **运算符** | **支持的类型** | **说明** | | # | **运算符** | **支持的类型** | **说明** |
| --- | :--------: | -------------- | --------------------------------------------------------------------------- | | --- | :--------: | -------------- | --------------------------------------------------------------------------- |
| 1 | AND | BOOL | 逻辑与,如果两个条件均为 TRUE 则返回 TRUE。如果任一为 FALSE则返回 FALSE | | 1 | AND | BOOL | 逻辑与,如果两个条件均为 TRUE则返回 TRUE。如果任一为 FALSE则返回 FALSE |
| 2 | OR | BOOL | 逻辑或,如果任一条件为 TRUE 则返回 TRUE。如果两者都是 FALSE则返回 FALSE | | 2 | OR | BOOL | 逻辑或,如果任一条件为 TRUE则返回 TRUE。如果两者都是 FALSE则返回 FALSE |
TDengine 在计算逻辑条件时,会进行短路径优化,即对于 AND第一个条件为 FALSE则不再计算第二个条件直接返回 FALSE对于 OR第一个条件为 TRUE则不再计算第二个条件直接返回 TRUE。 TDengine 在计算逻辑条件时,会进行短路径优化,即对于 AND第一个条件为 FALSE则不再计算第二个条件直接返回 FALSE对于 OR第一个条件为 TRUE则不再计算第二个条件直接返回 TRUE。

View File

@ -33,7 +33,7 @@ description: 对 JSON 类型如何使用的详细说明
## 支持的操作 ## 支持的操作
1. 在 where 条件中时,支持函数 match/nmatch/between and/like/and/or/is null/is not null不支持 in 1. 在 where 条件中时,支持函数 `match`、`nmatch`、`between and`、`like`、`and`、`or`、`is null`、`is not null`,不支持 `in`
``` ```
select * from s1 where info->'k1' match 'v*'; select * from s1 where info->'k1' match 'v*';
@ -47,7 +47,7 @@ description: 对 JSON 类型如何使用的详细说明
2. 支持 json tag 放在 group by、order by、join 子句、union all 以及子查询中,比如 group by json->'key' 2. 支持 json tag 放在 group by、order by、join 子句、union all 以及子查询中,比如 group by json->'key'
3. 支持 distinct 操作. 3. 支持 distinct 操作
``` ```
select distinct info->'k1' from s1 select distinct info->'k1' from s1
@ -69,8 +69,8 @@ description: 对 JSON 类型如何使用的详细说明
3. json 格式限制: 3. json 格式限制:
1. json 输入字符串可以为空("","\t"," "或 null或 object不能为非空的字符串布尔型和数组。 1. json 输入字符串可以为空(""、"\t"、" " 或 null或 object不能为非空的字符串布尔型和数组。
2. object 可为{},如果 object 为{},则整个 json 串记为空。key 可为"",若 key 为"",则 json 串中忽略该 k-v 对。 2. object 可为 {},如果 object 为 {},则整个 json 串记为空。key 可为 "",若 key 为 "",则 json 串中忽略该 k-v 对。
3. value 可以为数字(int/double)或字符串或 bool 或 null暂不可以为数组。不允许嵌套。 3. value 可以为数字(int/double)或字符串或 bool 或 null暂不可以为数组。不允许嵌套。
4. 若 json 字符串中出现两个相同的 key则第一个生效。 4. 若 json 字符串中出现两个相同的 key则第一个生效。
5. json 字符串里暂不支持转义。 5. json 字符串里暂不支持转义。

View File

@ -21,8 +21,8 @@ description: TDengine 中使用转义字符的详细规则
## 转义字符使用规则 ## 转义字符使用规则
1. 标识符里有转义字符(数据库名、表名、列名、别名) 1. 标识符里有转义字符(数据库名、表名、列名、别名)
1. 普通标识符: 直接提示错误的标识符,因为标识符规定必须是数字、字母和下划线,并且不能以数字开头。 1. 普通标识符:直接提示错误的标识符,因为标识符规定必须是数字、字母和下划线,并且不能以数字开头。
2. 反引号``标识符: 保持原样,不转义 2. 反引号 `` 标识符:保持原样,不转义
2. 数据里有转义字符 2. 数据里有转义字符
1. 遇到上面定义的转义字符会转义(`%`和`_`见下面说明),如果没有匹配的转义字符会忽略掉转义符`\ ``\x`保持原样)。 1. 遇到上面定义的转义字符会转义(`%`和`_`见下面说明),如果没有匹配的转义字符会忽略掉转义符 `\ ``\x`保持原样)。
2. 对于`%`和`_`,因为在`like`里这两个字符是通配符,所以在模式匹配`like`里用`\%`和`\_`表示字符里本身的`%`和`_`,如果在`like`模式匹配上下文之外使用`\%`或`\_`,则它们的计算结果为字符串`\%`和`\_`,而不是`%`和`_`。 2. 对于 `%` `_`,因为在 `like` 里这两个字符是通配符,所以在模式匹配 `like` 里用 `\%` `\_` 表示字符里本身的 `%` `_`,如果在 `like` 模式匹配上下文之外使用 `\%` `\_`,则它们的计算结果为字符串 `\%` `\_`,而不是 `%` `_`

View File

@ -9,13 +9,13 @@ description: 合法字符集和命名中的限制规则
1. 合法字符:英文字符、数字和下划线。 1. 合法字符:英文字符、数字和下划线。
1. 允许英文字符或下划线开头,不允许以数字开头。 1. 允许英文字符或下划线开头,不允许以数字开头。
1. 不区分大小写。 1. 不区分大小写。
1. 不能是[保留关键字](./20-keywords.md)。 1. 不能是 [保留关键字](./20-keywords.md)。
1. 转义后表(列)名规则: 1. 转义后表(列)名规则:
为了兼容支持更多形式的表TDengine 引入新的转义符 "`"。使用转义字符以后: 为了兼容支持更多形式的表TDengine 引入新的转义符 "`"。使用转义字符以后:
- 不再对转义字符中的内容进行大小写统一,即可以保留用户指定表名中的大小写属性,例如\`aBc\` 和 \`abc\` 是不同的表(列)名,但是 abc 和 aBc 是相同的表(列)名。 - 不再对转义字符中的内容进行大小写统一,即可以保留用户指定表名中的大小写属性,例如 \`aBc\` 和 \`abc\` 是不同的表(列)名,但是 abc 和 aBc 是相同的表(列)名。
- 可以创建包含字母、数字和下划线以外字符的表(列)名,例如:\`abc@TD\`,但是转义后名称中仍然不能包含`.`,否则会提示`The table name cannot contain '.'`。 - 可以创建包含字母、数字和下划线以外字符的表(列)名,例如:\`abc@TD\`,但是转义后名称中仍然不能包含`.`,否则会提示`The table name cannot contain '.'`。
- 可以创建以数字开头的表(列)名,例如\`1970\`。 - 可以创建以数字开头的表(列)名,例如 \`1970\`。
- 可以创建以[保留关键字](./20-keywords.md)命名的表(列)名,例如\`select\`。 - 可以创建以 [保留关键字](./20-keywords.md) 命名的表(列)名,例如 \`select\`。
## 密码合法字符集 ## 密码合法字符集
@ -27,7 +27,7 @@ description: 合法字符集和命名中的限制规则
- 数据库名最大长度为 64 字节 - 数据库名最大长度为 64 字节
- 表名最大长度为 192 字节,不包括数据库名前缀和分隔符 - 表名最大长度为 192 字节,不包括数据库名前缀和分隔符
- 每行数据最大长度 48KB从 3.0.5.0 版本开始为 64KB (注意:数据行内每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置) - 每行数据最大长度 48KBv3.0.5.0 开始为 64KB注意数据行内每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置)
- 列名最大长度为 64 字节 - 列名最大长度为 64 字节
- 最多允许 4096 列,最少需要 2 列,第一列必须是时间戳。 - 最多允许 4096 列,最少需要 2 列,第一列必须是时间戳。
- 标签名最大长度为 64 字节 - 标签名最大长度为 64 字节

View File

@ -32,9 +32,9 @@ DROP DNODE dnode_id [force] [unsafe]
注意删除 dnode 不等于停止相应的进程。实际中推荐先将一个 dnode 删除之后再停止其所对应的进程。 注意删除 dnode 不等于停止相应的进程。实际中推荐先将一个 dnode 删除之后再停止其所对应的进程。
只有在线节点可以被删除。如果要强制删除离线节点,需要执行强制删除操作, 即指定force选项。 只有在线节点可以被删除。如果要强制删除离线节点,需要执行强制删除操作, 即指定 force 选项。
当节点上存在单副本并且节点处于离线如果要强制删除该节点需要执行非安全删除即制定unsafe并且数据不可再恢复。 当节点上存在单副本,并且节点处于离线,如果要强制删除该节点,需要执行非安全删除,即制定 unsafe并且数据不可再恢复。
## 修改数据节点配置 ## 修改数据节点配置
@ -44,27 +44,27 @@ ALTER DNODE dnode_id dnode_option
ALTER ALL DNODES dnode_option ALTER ALL DNODES dnode_option
``` ```
对于支持动态修改的配置参数,您可以使用 ALTER DNODE 或 ALTER ALL DNODES 语法修改 dnode 中配置参数的值,自 3.3.4.0 后,修改的配置参数将自动持久化,即便数据库服务重启后仍然生效。 对于支持动态修改的配置参数,您可以使用 ALTER DNODE 或 ALTER ALL DNODES 语法修改 dnode 中配置参数的值,自 v3.3.4.0 后,修改的配置参数将自动持久化,即便数据库服务重启后仍然生效。
对于一个配置参数是否支持动态修改,请您参考以下页面:[taosd 参考手册](../01-components/01-taosd.md) 对于一个配置参数是否支持动态修改,请您参考 [taosd 参考手册](../01-components/01-taosd.md)
value 是参数的值,需要是字符格式。如修改 dnode 1 的日志输出级别为 debug value 是参数的值,需要是字符格式。如修改 dnode 1 的日志输出级别为 debug
```sql ```sql
ALTER DNODE 1 'debugFlag' '143'; ALTER DNODE 1 'debugFlag' '143';
``` ```
### 补充说明: ### 补充说明:
配置参数在 dnode 中被分为全局配置参数与局部配置参数,您可以查看 SHOW VARIABLES 或 SHOW DNODE dnode_id VARIABLE 中的 category 字段来确认配置参数属于全局配置参数还是局部配置参数 配置参数在 dnode 中被分为全局配置参数与局部配置参数,您可以查看 SHOW VARIABLES 或 SHOW DNODE dnode_id VARIABLE 中的 category 字段来确认配置参数属于全局配置参数还是局部配置参数
1. 局部配置参数:您可以使用 ALTER DNODE 或 ALTER ALL DNODES 来更新某一个 dnode 或全部 dnodes 的局部配置参数。 1. 局部配置参数:您可以使用 ALTER DNODE 或 ALTER ALL DNODES 来更新某一个 dnode 或全部 dnodes 的局部配置参数。
2. 全局配置参数:全局配置参数要求各个 dnode 保持一致,所以您只可以使用 ALTER ALL DNODES 来更新全部 dnodes 的全局配置参数。 2. 全局配置参数:全局配置参数要求各个 dnode 保持一致,所以您只可以使用 ALTER ALL DNODES 来更新全部 dnodes 的全局配置参数。
配置参数是否可以动态修改,有以下三种情况: 配置参数是否可以动态修改,有以下三种情况:
1. 支持动态修改 立即生效 1. 支持动态修改立即生效
2. 支持动态修改 重启生效 2. 支持动态修改重启生效
3. 不支持动态修改 3. 不支持动态修改
对于重启后生效的配置参数,您可以通过 SHOW VARIABLES 或 SHOW DNODE dnode_id VARIABLE 看到修改后的值,但是需要重启数据库服务才使其生效。 对于重启后生效的配置参数,您可以通过 `SHOW VARIABLES``SHOW DNODE dnode_id VARIABLE` 看到修改后的值,但是需要重启数据库服务才使其生效。
## 添加管理节点 ## 添加管理节点
@ -96,7 +96,7 @@ DROP MNODE ON DNODE dnode_id;
CREATE QNODE ON DNODE dnode_id; CREATE QNODE ON DNODE dnode_id;
``` ```
系统启动默认没有 QNODE用户可以创建 QNODE 来实现计算和存储的分离。一个 DNODE 上只能创建一个 QNODE。一个 DNODE`supportVnodes` 参数如果不为 0同时又在其上创建上 QNODE则在该 dnode 中既有负责存储管理的 vnode 又有负责查询计算的 qnode如果还在该 dnode 上创建了 mnode则一个 dnode 上最多三种逻辑节点都可以存在。但通过配置也可以使其彻底分离。将一个 dnode 的`supportVnodes`配置为 0可以选择在其上创建 mnode 或者 qnode 中的一种,这样可以实现三种逻辑节点在物理上的彻底分离。 系统启动默认没有 QNODE用户可以创建 QNODE 来实现计算和存储的分离。一个 dnode 上只能创建一个 QNODE。一个 dnode`supportVnodes` 参数如果不为 0同时又在其上创建上 QNODE则在该 dnode 中既有负责存储管理的 vnode 又有负责查询计算的 qnode如果还在该 dnode 上创建了 mnode则一个 dnode 上最多三种逻辑节点都可以存在。但通过配置也可以使其彻底分离。将一个 dnode 的`supportVnodes`配置为 0可以选择在其上创建 mnode 或者 qnode 中的一种,这样可以实现三种逻辑节点在物理上的彻底分离。
## 查看查询节点 ## 查看查询节点
@ -104,7 +104,7 @@ CREATE QNODE ON DNODE dnode_id;
SHOW QNODES; SHOW QNODES;
``` ```
列出集群中所有查询节点,包括 ID及所在 DNODE。 列出集群中所有查询节点,包括 ID及所在 dnode
## 删除查询节点 ## 删除查询节点
@ -112,7 +112,7 @@ SHOW QNODES;
DROP QNODE ON DNODE dnode_id; DROP QNODE ON DNODE dnode_id;
``` ```
删除 ID 为 dnode_id 的 DNODE 上的 QNODE,但并不会影响该 dnode 的状态。 删除 ID 为 dnode_id 的 dnode 上的 qnode,但并不会影响该 dnode 的状态。
## 查询集群状态 ## 查询集群状态
@ -120,7 +120,10 @@ DROP QNODE ON DNODE dnode_id;
SHOW CLUSTER ALIVE; SHOW CLUSTER ALIVE;
``` ```
查询当前集群的状态是否可用,返回值: 0不可用 1完全可用 2部分可用集群中部分节点下线但其它节点仍可以正常使用 查询当前集群的状态是否可用,返回值
- 0不可用
- 1完全可用
- 2部分可用集群中部分节点下线但其它节点仍可以正常使用
## 修改客户端配置 ## 修改客户端配置

View File

@ -4,7 +4,7 @@ title: 元数据
description: Information_Schema 数据库中存储了系统中所有的元数据信息 description: Information_Schema 数据库中存储了系统中所有的元数据信息
--- ---
TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数据库元数据、数据库系统信息和状态的访问,例如数据库或表的名称,当前执行的 SQL 语句等。该数据库存储有关 TDengine 维护的所有其他数据库的信息。它包含多个只读表。实际上,这些表都是视图,而不是基表,因此没有与它们关联的文件。所以对这些表只能查询,不能进行 INSERT 等写入操作。`INFORMATION_SCHEMA` 数据库旨在以一种更一致的方式来提供对 TDengine 支持的各种 SHOW 语句(如 SHOW TABLES、SHOW DATABASES所提供的信息的访问。与 SHOW 语句相比,使用 SELECT ... FROM INFORMATION_SCHEMA.tablename 具有以下优点: TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数据库元数据、数据库系统信息和状态的访问,例如数据库或表的名称,当前执行的 SQL 语句等。该数据库存储有关 TDengine 维护的所有其他数据库的信息。它包含多个只读表。实际上,这些表都是视图,而不是基表,因此没有与它们关联的文件。所以对这些表只能查询,不能进行 INSERT 等写入操作。`INFORMATION_SCHEMA` 数据库旨在以一种更一致的方式来提供对 TDengine 支持的各种 SHOW 语句(如 SHOW TABLES、SHOW DATABASES所提供的信息的访问。与 SHOW 语句相比,使用 `SELECT ... FROM INFORMATION_SCHEMA.tablename` 具有以下优点。
1. 可以使用 USE 语句将 INFORMATION_SCHEMA 设为默认数据库 1. 可以使用 USE 语句将 INFORMATION_SCHEMA 设为默认数据库
2. 可以使用 SELECT 语句熟悉的语法,只需要学习一些表名和列名 2. 可以使用 SELECT 语句熟悉的语法,只需要学习一些表名和列名
@ -15,7 +15,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
:::info :::info
- 由于 SHOW 语句已经被开发者熟悉和广泛使用,所以它们仍然被保留。 - 由于 SHOW 语句已经被开发者熟悉和广泛使用,所以它们仍然被保留。
- 系统表中的一些列可能是关键字,在查询时需要使用转义符'\`',例如查询数据库 test 有几个 VGROUP - 系统表中的一些列可能是关键字,在查询时需要使用转义符 '\`',例如查询数据库 test 有几个 VGROUP
```sql ```sql
select `vgroups` from ins_databases where name = 'test'; select `vgroups` from ins_databases where name = 'test';
``` ```
@ -26,11 +26,11 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
## INS_DNODES ## INS_DNODES
提供 dnode 的相关信息。也可以使用 SHOW DNODES 来查询这些信息。 SYSINFO 为 0 的用户不能查看此表。 提供 dnode 的相关信息。也可以使用 SHOW DNODES 来查询这些信息。SYSINFO 为 0 的用户不能查看此表。
| # | **列名** | **数据类型** | **说明** | | # | **列名** | **数据类型** | **说明** |
| --- | :------------: | ------------ | ----------------------------------------------------------------------------------------------------- | | --- | :------------: | ------------ | ----------------------------------------------------------------------------------------------------- |
| 1 | vnodes | SMALLINT | dnode 中的实际 vnode 个数。需要注意,`vnodes` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 1 | vnodes | SMALLINT | dnode 中的实际 vnode 个数。需要注意,`vnodes` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 2 | support_vnodes | SMALLINT | 最多支持的 vnode 个数 | | 2 | support_vnodes | SMALLINT | 最多支持的 vnode 个数 |
| 3 | status | BINARY(10) | 当前状态 | | 3 | status | BINARY(10) | 当前状态 |
| 4 | note | BINARY(256) | 离线原因等信息 | | 4 | note | BINARY(256) | 离线原因等信息 |
@ -40,7 +40,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
## INS_MNODES ## INS_MNODES
提供 mnode 的相关信息。也可以使用 SHOW MNODES 来查询这些信息。 SYSINFO 为 0 的用户不能查看此表。 提供 mnode 的相关信息。也可以使用 SHOW MNODES 来查询这些信息。SYSINFO 为 0 的用户不能查看此表。
| # | **列名** | **数据类型** | **说明** | | # | **列名** | **数据类型** | **说明** |
| --- | :---------: | ------------ | ------------------ | | --- | :---------: | ------------ | ------------------ |
@ -73,7 +73,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
## INS_CLUSTER ## INS_CLUSTER
存储集群相关信息。 SYSINFO 属性为 0 的用户不能查看此表。 存储集群相关信息。SYSINFO 属性为 0 的用户不能查看此表。
| # | **列名** | **数据类型** | **说明** | | # | **列名** | **数据类型** | **说明** |
| --- | :---------: | ------------ | ---------- | | --- | :---------: | ------------ | ---------- |
@ -90,31 +90,31 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 1 | name | VARCHAR(64) | 数据库名 | | 1 | name | VARCHAR(64) | 数据库名 |
| 2 | create_time | TIMESTAMP | 创建时间 | | 2 | create_time | TIMESTAMP | 创建时间 |
| 3 | ntables | INT | 数据库中表的数量,包含子表和普通表但不包含超级表 | | 3 | ntables | INT | 数据库中表的数量,包含子表和普通表但不包含超级表 |
| 4 | vgroups | INT | 数据库中有多少个 vgroup。需要注意`vgroups` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 4 | vgroups | INT | 数据库中有多少个 vgroup。需要注意`vgroups` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 6 | replica | INT | 副本数。需要注意,`replica` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 6 | replica | INT | 副本数。需要注意,`replica` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 7 | strict | VARCHAR(4) | 废弃参数 | | 7 | strict | VARCHAR(4) | 废弃参数 |
| 8 | duration | VARCHAR(10) | 单文件存储数据的时间跨度。需要注意,`duration` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。内部存储单位为分钟,查询时有可能转换为天或小时展示 | | 8 | duration | VARCHAR(10) | 单文件存储数据的时间跨度。需要注意,`duration` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。内部存储单位为分钟,查询时有可能转换为天或小时展示 |
| 9 | keep | VARCHAR(32) | 数据保留时长。需要注意,`keep` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 内部存储单位为分钟,查询时有可能转换为天或小时展示 | | 9 | keep | VARCHAR(32) | 数据保留时长。需要注意,`keep` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 内部存储单位为分钟,查询时有可能转换为天或小时展示 |
| 10 | buffer | INT | 每个 vnode 写缓存的内存块大小,单位 MB。需要注意`buffer` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 10 | buffer | INT | 每个 vnode 写缓存的内存块大小,单位 MB。需要注意`buffer` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 11 | pagesize | INT | 每个 VNODE 中元数据存储引擎的页大小,单位为 KB。需要注意`pagesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 11 | pagesize | INT | 每个 VNODE 中元数据存储引擎的页大小,单位为 KB。需要注意`pagesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 12 | pages | INT | 每个 vnode 元数据存储引擎的缓存页个数。需要注意,`pages` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 12 | pages | INT | 每个 vnode 元数据存储引擎的缓存页个数。需要注意,`pages` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 13 | minrows | INT | 文件块中记录的最小条数。需要注意,`minrows` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 13 | minrows | INT | 文件块中记录的最小条数。需要注意,`minrows` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 14 | maxrows | INT | 文件块中记录的最大条数。需要注意,`maxrows` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 14 | maxrows | INT | 文件块中记录的最大条数。需要注意,`maxrows` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 15 | comp | INT | 数据压缩方式。需要注意,`comp` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 15 | comp | INT | 数据压缩方式。需要注意,`comp` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 16 | precision | VARCHAR(2) | 时间分辨率。需要注意,`precision` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 16 | precision | VARCHAR(2) | 时间分辨率。需要注意,`precision` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 17 | status | VARCHAR(10) | 数据库状态 | | 17 | status | VARCHAR(10) | 数据库状态 |
| 18 | retentions | VARCHAR(60) | 数据的聚合周期和保存时长。需要注意,`retentions` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 18 | retentions | VARCHAR(60) | 数据的聚合周期和保存时长。需要注意,`retentions` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 19 | single_stable | BOOL | 表示此数据库中是否只可以创建一个超级表。需要注意,`single_stable` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 19 | single_stable | BOOL | 表示此数据库中是否只可以创建一个超级表。需要注意,`single_stable` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 20 | cachemodel | VARCHAR(60) | 表示是否在内存中缓存子表的最近数据。需要注意,`cachemodel` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 20 | cachemodel | VARCHAR(60) | 表示是否在内存中缓存子表的最近数据。需要注意,`cachemodel` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 21 | cachesize | INT | 表示每个 vnode 中用于缓存子表最近数据的内存大小。需要注意,`cachesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 21 | cachesize | INT | 表示每个 vnode 中用于缓存子表最近数据的内存大小。需要注意,`cachesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 22 | wal_level | INT | WAL 级别。需要注意,`wal_level` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 22 | wal_level | INT | WAL 级别。需要注意,`wal_level` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 23 | wal_fsync_period | INT | 数据落盘周期。需要注意,`wal_fsync_period` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 23 | wal_fsync_period | INT | 数据落盘周期。需要注意,`wal_fsync_period` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 24 | wal_retention_period | INT | WAL 的保存时长,单位为秒。需要注意,`wal_retention_period` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 24 | wal_retention_period | INT | WAL 的保存时长,单位为秒。需要注意,`wal_retention_period` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 25 | wal_retention_size | INT | WAL 的保存上限。需要注意,`wal_retention_size` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 25 | wal_retention_size | INT | WAL 的保存上限。需要注意,`wal_retention_size` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 26 | stt_trigger | SMALLINT | 触发文件合并的落盘文件的个数。需要注意,`stt_trigger` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 26 | stt_trigger | SMALLINT | 触发文件合并的落盘文件的个数。需要注意,`stt_trigger` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 27 | table_prefix | SMALLINT | 内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的前缀的长度。需要注意,`table_prefix` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 27 | table_prefix | SMALLINT | 内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的前缀的长度。需要注意,`table_prefix` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 28 | table_suffix | SMALLINT | 内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的后缀的长度。需要注意,`table_suffix` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 28 | table_suffix | SMALLINT | 内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的后缀的长度。需要注意,`table_suffix` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 29 | tsdb_pagesize | INT | 时序数据存储引擎中的页大小。需要注意,`tsdb_pagesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 29 | tsdb_pagesize | INT | 时序数据存储引擎中的页大小。需要注意,`tsdb_pagesize` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
## INS_FUNCTIONS ## INS_FUNCTIONS
@ -123,15 +123,15 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| # | **列名** | **数据类型** | **说明** | | # | **列名** | **数据类型** | **说明** |
| --- | :-----------: | ------------- | --------------------------------------------------------------------------------------------- | | --- | :-----------: | ------------- | --------------------------------------------------------------------------------------------- |
| 1 | name | VARCHAR(64) | 函数名 | | 1 | name | VARCHAR(64) | 函数名 |
| 2 | comment | VARCHAR(255) | 补充说明。需要注意,`comment` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 2 | comment | VARCHAR(255) | 补充说明。需要注意,`comment` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 3 | aggregate | INT | 是否为聚合函数。需要注意,`aggregate` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 3 | aggregate | INT | 是否为聚合函数。需要注意,`aggregate` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 4 | output_type | VARCHAR(31) | 输出类型 | | 4 | output_type | VARCHAR(31) | 输出类型 |
| 5 | create_time | TIMESTAMP | 创建时间 | | 5 | create_time | TIMESTAMP | 创建时间 |
| 6 | code_len | INT | 代码长度 | | 6 | code_len | INT | 代码长度 |
| 7 | bufsize | INT | buffer 大小 | | 7 | bufsize | INT | buffer 大小 |
| 8 | func_language | VARCHAR(31) | 自定义函数编程语言 | | 8 | func_language | VARCHAR(31) | 自定义函数编程语言 |
| 9 | func_body | VARCHAR(16384) | 函数体定义 | | 9 | func_body | VARCHAR(16384) | 函数体定义 |
| 10 | func_version | INT | 函数版本号。初始版本为0每次替换更新版本号加1。 | | 10 | func_version | INT | 函数版本号。初始版本为0每次替换更新版本号加1。 |
## INS_INDEXES ## INS_INDEXES
@ -145,7 +145,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 3 | index_name | VARCHAR(192) | 索引名 | | 3 | index_name | VARCHAR(192) | 索引名 |
| 4 | column_name | VARCHAR(64) | 建索引的列的列名 | | 4 | column_name | VARCHAR(64) | 建索引的列的列名 |
| 5 | index_type | VARCHAR(10) | 目前有 SMA 和 tag | | 5 | index_type | VARCHAR(10) | 目前有 SMA 和 tag |
| 6 | index_extensions | VARCHAR(256) | 索引的额外信息。对 SMA/tag 类型的索引,是函数名的列表。 | | 6 | index_extensions | VARCHAR(256) | 索引的额外信息。对 SMA/tag 类型的索引,是函数名的列表。|
## INS_STABLES ## INS_STABLES
@ -157,12 +157,12 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 2 | db_name | VARCHAR(64) | 超级表所在的数据库的名称 | | 2 | db_name | VARCHAR(64) | 超级表所在的数据库的名称 |
| 3 | create_time | TIMESTAMP | 创建时间 | | 3 | create_time | TIMESTAMP | 创建时间 |
| 4 | columns | INT | 列数目 | | 4 | columns | INT | 列数目 |
| 5 | tags | INT | 标签数目。需要注意,`tags` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 5 | tags | INT | 标签数目。需要注意,`tags` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 6 | last_update | TIMESTAMP | 最后更新时间 | | 6 | last_update | TIMESTAMP | 最后更新时间 |
| 7 | table_comment | VARCHAR(1024) | 表注释 | | 7 | table_comment | VARCHAR(1024) | 表注释 |
| 8 | watermark | VARCHAR(64) | 窗口的关闭时间。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 8 | watermark | VARCHAR(64) | 窗口的关闭时间。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 9 | max_delay | VARCHAR(64) | 推送计算结果的最大延迟。需要注意,`max_delay` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 9 | max_delay | VARCHAR(64) | 推送计算结果的最大延迟。需要注意,`max_delay` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 10 | rollup | VARCHAR(128) | rollup 聚合函数。需要注意,`rollup` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 10 | rollup | VARCHAR(128) | rollup 聚合函数。需要注意,`rollup` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
## INS_TABLES ## INS_TABLES
@ -177,7 +177,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 5 | stable_name | VARCHAR(192) | 所属的超级表表名 | | 5 | stable_name | VARCHAR(192) | 所属的超级表表名 |
| 6 | uid | BIGINT | 表 id | | 6 | uid | BIGINT | 表 id |
| 7 | vgroup_id | INT | vgroup id | | 7 | vgroup_id | INT | vgroup id |
| 8 | ttl | INT | 表的生命周期。需要注意`ttl` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 8 | ttl | INT | 表的生命周期。需要注意 `ttl` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 9 | table_comment | VARCHAR(1024) | 表注释 | | 9 | table_comment | VARCHAR(1024) | 表注释 |
| 10 | type | VARCHAR(21) | 表类型 | | 10 | type | VARCHAR(21) | 表类型 |
@ -215,7 +215,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 1 | name | VARCHAR(24) | 用户名 | | 1 | name | VARCHAR(24) | 用户名 |
| 2 | super | TINYINT | 用户是否为超级用户10否 | | 2 | super | TINYINT | 用户是否为超级用户10否 |
| 3 | enable | TINYINT | 用户是否启用10否 | | 3 | enable | TINYINT | 用户是否启用10否 |
| 4 | sysinfo | TINYINT | 用户是否可查看系统信息1, 0否 | | 4 | sysinfo | TINYINT | 用户是否可查看系统信息10否 |
| 5 | create_time | TIMESTAMP | 创建时间 | | 5 | create_time | TIMESTAMP | 创建时间 |
| 6 | allowed_host | VARCHAR(49152)| IP 白名单 | | 6 | allowed_host | VARCHAR(49152)| IP 白名单 |
@ -227,13 +227,13 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| --- | :---------: | ------------ | --------------------------------------------------------------------------------------------------------- | | --- | :---------: | ------------ | --------------------------------------------------------------------------------------------------------- |
| 1 | version | VARCHAR(9) | 企业版授权说明official(官方授权的)/trial(试用的) | | 1 | version | VARCHAR(9) | 企业版授权说明official(官方授权的)/trial(试用的) |
| 2 | cpu_cores | VARCHAR(9) | 授权使用的 CPU 核心数量 | | 2 | cpu_cores | VARCHAR(9) | 授权使用的 CPU 核心数量 |
| 3 | dnodes | VARCHAR(10) | 授权使用的 dnode 节点数量。需要注意,`dnodes` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 3 | dnodes | VARCHAR(10) | 授权使用的 dnode 节点数量。需要注意,`dnodes` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 4 | streams | VARCHAR(10) | 授权创建的流数量。需要注意,`streams` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 4 | streams | VARCHAR(10) | 授权创建的流数量。需要注意,`streams` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 5 | users | VARCHAR(10) | 授权创建的用户数量。需要注意,`users` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 5 | users | VARCHAR(10) | 授权创建的用户数量。需要注意,`users` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 6 | accounts | VARCHAR(10) | 授权创建的帐户数量。需要注意,`accounts` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 6 | accounts | VARCHAR(10) | 授权创建的帐户数量。需要注意,`accounts` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 7 | storage | VARCHAR(21) | 授权使用的存储空间大小。需要注意,`storage` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 7 | storage | VARCHAR(21) | 授权使用的存储空间大小。需要注意,`storage` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 8 | connections | VARCHAR(21) | 授权使用的客户端连接数量。需要注意,`connections` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 8 | connections | VARCHAR(21) | 授权使用的客户端连接数量。需要注意,`connections` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 9 | databases | VARCHAR(11) | 授权使用的数据库数量。需要注意,`databases` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 9 | databases | VARCHAR(11) | 授权使用的数据库数量。需要注意,`databases` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 10 | speed | VARCHAR(9) | 授权使用的数据点每秒写入数量 | | 10 | speed | VARCHAR(9) | 授权使用的数据点每秒写入数量 |
| 11 | querytime | VARCHAR(9) | 授权使用的查询总时长 | | 11 | querytime | VARCHAR(9) | 授权使用的查询总时长 |
| 12 | timeseries | VARCHAR(21) | 授权使用的测点数量 | | 12 | timeseries | VARCHAR(21) | 授权使用的测点数量 |
@ -248,7 +248,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| --- | :-------: | ------------ | ------------------------------------------------------------------------------------------------ | | --- | :-------: | ------------ | ------------------------------------------------------------------------------------------------ |
| 1 | vgroup_id | INT | vgroup id | | 1 | vgroup_id | INT | vgroup id |
| 2 | db_name | VARCHAR(32) | 数据库名 | | 2 | db_name | VARCHAR(32) | 数据库名 |
| 3 | tables | INT | 此 vgroup 内有多少表。需要注意,`tables` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 3 | tables | INT | 此 vgroup 内有多少表。需要注意,`tables` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
| 4 | status | VARCHAR(10) | 此 vgroup 的状态 | | 4 | status | VARCHAR(10) | 此 vgroup 的状态 |
| 5 | v1_dnode | INT | 第一个成员所在的 dnode 的 id | | 5 | v1_dnode | INT | 第一个成员所在的 dnode 的 id |
| 6 | v1_status | VARCHAR(10) | 第一个成员的状态 | | 6 | v1_status | VARCHAR(10) | 第一个成员的状态 |
@ -258,7 +258,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 10 | v3_status | VARCHAR(10) | 第三个成员的状态 | | 10 | v3_status | VARCHAR(10) | 第三个成员的状态 |
| 11 | nfiles | INT | 此 vgroup 中数据/元数据文件的数量 | | 11 | nfiles | INT | 此 vgroup 中数据/元数据文件的数量 |
| 12 | file_size | INT | 此 vgroup 中数据/元数据文件的大小 | | 12 | file_size | INT | 此 vgroup 中数据/元数据文件的大小 |
| 13 | tsma | TINYINT | 此 vgroup 是否专用于 Time-range-wise SMA1: 是, 0: 否 | | 13 | tsma | TINYINT | 此 vgroup 是否专用于 Time-range-wise SMA1: 是0: 否 |
## INS_CONFIGS ## INS_CONFIGS
@ -267,7 +267,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| # | **列名** | **数据类型** | **说明** | | # | **列名** | **数据类型** | **说明** |
| --- | :------: | ------------ | --------------------------------------------------------------------------------------- | | --- | :------: | ------------ | --------------------------------------------------------------------------------------- |
| 1 | name | VARCHAR(32) | 配置项名称 | | 1 | name | VARCHAR(32) | 配置项名称 |
| 2 | value | VARCHAR(64) | 该配置项的值。需要注意,`value` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 2 | value | VARCHAR(64) | 该配置项的值。需要注意,`value` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
## INS_DNODE_VARIABLES ## INS_DNODE_VARIABLES
@ -277,7 +277,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| --- | :------: | ------------ | --------------------------------------------------------------------------------------- | | --- | :------: | ------------ | --------------------------------------------------------------------------------------- |
| 1 | dnode_id | INT | dnode 的 ID | | 1 | dnode_id | INT | dnode 的 ID |
| 2 | name | VARCHAR(32) | 配置项名称 | | 2 | name | VARCHAR(32) | 配置项名称 |
| 3 | value | VARCHAR(64) | 该配置项的值。需要注意,`value` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 3 | value | VARCHAR(64) | 该配置项的值。需要注意,`value` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
## INS_TOPICS ## INS_TOPICS
@ -312,7 +312,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
| 5 | source_db | VARCHAR(64) | 源数据库 | | 5 | source_db | VARCHAR(64) | 源数据库 |
| 6 | target_db | VARCHAR(64) | 目的数据库 | | 6 | target_db | VARCHAR(64) | 目的数据库 |
| 7 | target_table | VARCHAR(192) | 流计算写入的目标表 | | 7 | target_table | VARCHAR(192) | 流计算写入的目标表 |
| 8 | watermark | BIGINT | watermark详见 SQL 手册流式计算。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 8 | watermark | BIGINT | watermark详见 SQL 手册流式计算。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 |
| 9 | trigger | INT | 计算结果推送模式,详见 SQL 手册流式计算。需要注意,`trigger` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。| | 9 | trigger | INT | 计算结果推送模式,详见 SQL 手册流式计算。需要注意,`trigger` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。|
## INS_USER_PRIVILEGES ## INS_USER_PRIVILEGES
@ -333,14 +333,14 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数
|:----|:-----------|:------------|:--------| |:----|:-----------|:------------|:--------|
| 1 | db_name | VARCHAR(32) | 数据库名称 | | 1 | db_name | VARCHAR(32) | 数据库名称 |
| 2 | vgroup_id | INT | vgroup 的 ID | | 2 | vgroup_id | INT | vgroup 的 ID |
| 3 | wal | BIGINT | wal 文件大小, 单位为 K | | 3 | wal | BIGINT | wal 文件大小,单位为 KB |
| 4 | data1 | BIGINT | 一级存储上数据文件的大小,单位为KB | | 4 | data1 | BIGINT | 一级存储上数据文件的大小,单位为 KB |
| 5 | data2 | BIGINT | 二级存储上数据文件的大小,单位为 KB | | 5 | data2 | BIGINT | 二级存储上数据文件的大小单位为 KB |
| 6 | data3 | BIGINT | 三级存储上数据文件的大小, 单位为KB | | 6 | data3 | BIGINT | 三级存储上数据文件的大小,单位为 KB |
| 7 | cache_rdb | BIGINT | last/last_row 文件的大小,单位为KB | | 7 | cache_rdb | BIGINT | last/last_row 文件的大小,单位为 KB |
| 8 | table_meta | BIGINT | meta 文件的大小, 单位为KB | | 8 | table_meta | BIGINT | meta 文件的大小,单位为 KB |
| 9 | s3 | BIGINT | s3 上占用的大小, 单位为KB | | 9 | s3 | BIGINT | s3 上占用的大小,单位为 KB |
| 10 | raw_data | BIGINT | 预估的原始数据的大小, 单位为KB | | 10 | raw_data | BIGINT | 预估的原始数据的大小,单位为 KB |
## INS_FILESETS ## INS_FILESETS

View File

@ -14,7 +14,7 @@ TDengine 3.0 版本开始提供一个内置数据库 `performance_schema`,其
| --- | :----------: | ------------ | ------------------------------- | | --- | :----------: | ------------ | ------------------------------- |
| 1 | app_id | UBIGINT | 客户端 ID | | 1 | app_id | UBIGINT | 客户端 ID |
| 2 | ip | BINARY(16) | 客户端地址 | | 2 | ip | BINARY(16) | 客户端地址 |
| 3 | pid | INT | 客户端进程 号 | | 3 | pid | INT | 客户端进程号 |
| 4 | name | BINARY(24) | 客户端名称 | | 4 | name | BINARY(24) | 客户端名称 |
| 5 | start_time | TIMESTAMP | 客户端启动时间 | | 5 | start_time | TIMESTAMP | 客户端启动时间 |
| 6 | insert_req | UBIGINT | insert 请求次数 | | 6 | insert_req | UBIGINT | insert 请求次数 |
@ -69,7 +69,7 @@ TDengine 3.0 版本开始提供一个内置数据库 `performance_schema`,其
| 1 | consumer_id | BIGINT | 消费者的唯一 ID | | 1 | consumer_id | BIGINT | 消费者的唯一 ID |
| 2 | consumer_group | BINARY(192) | 消费者组 | | 2 | consumer_group | BINARY(192) | 消费者组 |
| 3 | client_id | BINARY(192) | 用户自定义字符串,通过创建 consumer 时指定 client_id 来展示 | | 3 | client_id | BINARY(192) | 用户自定义字符串,通过创建 consumer 时指定 client_id 来展示 |
| 4 | status | BINARY(20) | 消费者当前状态。消费者状态包括ready(正常可用)、 lost(连接已丢失)、 rebalancing(消费者所属 vgroup 正在分配中)、unknown(未知状态)| | 4 | status | BINARY(20) | 消费者当前状态。消费者状态包括ready(正常可用)、lost(连接已丢失)、rebalancing(消费者所属 vgroup 正在分配中)、unknown(未知状态)|
| 5 | topics | BINARY(204) | 被订阅的 topic。若订阅多个 topic则展示为多行 | | 5 | topics | BINARY(204) | 被订阅的 topic。若订阅多个 topic则展示为多行 |
| 6 | up_time | TIMESTAMP | 第一次连接 taosd 的时间 | | 6 | up_time | TIMESTAMP | 第一次连接 taosd 的时间 |
| 7 | subscribe_time | TIMESTAMP | 上一次发起订阅的时间 | | 7 | subscribe_time | TIMESTAMP | 上一次发起订阅的时间 |

View File

@ -20,7 +20,7 @@ SHOW APPS;
SHOW CLUSTER; SHOW CLUSTER;
``` ```
显示当前集群的信息 显示当前集群的信息
## SHOW CLUSTER ALIVE ## SHOW CLUSTER ALIVE
@ -28,17 +28,22 @@ SHOW CLUSTER;
SHOW CLUSTER ALIVE; SHOW CLUSTER ALIVE;
``` ```
查询当前集群的状态是否可用,返回值: 0不可用 1完全可用 2部分可用集群中部分节点下线但其它节点仍可以正常使用 查询当前集群的状态是否可用,返回值如下
- 0不可用
- 1完全可用
- 2部分可用集群中部分节点下线但其它节点仍可以正常使用
## SHOW CLUSTER MACHINES ## SHOW CLUSTER MACHINES
```sql ```sql
SHOW CLUSTER MACHINES; // 从 TDengine 3.2.3.0 版本开始支持 SHOW CLUSTER MACHINES;
``` ```
显示集群的机器码等信息。 显示集群的机器码等信息。
注:企业版独有 备注
- 企业版功能
- v3.2.3.0 开始支持
## SHOW CONNECTIONS ## SHOW CONNECTIONS
@ -70,7 +75,7 @@ SHOW CREATE DATABASE db_name;
SHOW CREATE STABLE [db_name.]stb_name; SHOW CREATE STABLE [db_name.]stb_name;
``` ```
显示 tb_name 指定的超级表的创建语句 显示 tb_name 指定的超级表的创建语句
## SHOW CREATE TABLE ## SHOW CREATE TABLE
@ -114,7 +119,8 @@ SHOW GRANTS FULL; // 从 TDengine 3.2.3.0 版本开始支持
显示企业版许可授权的信息。 显示企业版许可授权的信息。
注:企业版独有 备注
- 企业版功能
## SHOW INDEXES ## SHOW INDEXES
@ -147,7 +153,7 @@ SHOW MNODES;
SHOW QNODES; SHOW QNODES;
``` ```
显示当前系统中 QNODE (查询节点)的信息。 显示当前系统中 QNODE查询节点的信息。
## SHOW QUERIES ## SHOW QUERIES
@ -155,7 +161,7 @@ SHOW QNODES;
SHOW QUERIES; SHOW QUERIES;
``` ```
显示当前系统中正在进行的写入(更新)/查询/删除。(由于内部 API 命名原因,所以统称 QUERIES 显示当前系统中正在进行的写入(更新)、查询、删除。(由于内部 API 命名原因,所以统称 QUERIES
## SHOW SCORES ## SHOW SCORES
@ -165,7 +171,8 @@ SHOW SCORES;
显示系统被许可授权的容量的信息。 显示系统被许可授权的容量的信息。
注:企业版独有。 备注
- 企业版功能
## SHOW STABLES ## SHOW STABLES
@ -219,11 +226,11 @@ SHOW TABLE DISTRIBUTED table_name;
_block_dist: Total_Blocks=[5] Total_Size=[93.65 KB] Average_size=[18.73 KB] Compression_Ratio=[23.98 %] _block_dist: Total_Blocks=[5] Total_Size=[93.65 KB] Average_size=[18.73 KB] Compression_Ratio=[23.98 %]
Total_Blocks: 表 d0 占用的 block 个数为 5 个 Total_Blocks表 d0 占用的 block 个数为 5 个
Total_Size: 表 d0 所有 block 在文件中占用的大小为 93.65 KB Total_Size 表 d0 所有 block 在文件中占用的大小为 93.65 KB
Average_size: 平均每个 block 在文件中占用的空间大小为 18.73 KB Average_size平均每个 block 在文件中占用的空间大小为 18.73 KB
Compression_Ratio: 数据压缩率 23.98% Compression_Ratio: 数据压缩率 23.98%
@ -232,7 +239,7 @@ Compression_Ratio: 数据压缩率 23.98%
_block_dist: Total_Rows=[20000] Inmem_Rows=[0] MinRows=[3616] MaxRows=[4096] Average_Rows=[4000] _block_dist: Total_Rows=[20000] Inmem_Rows=[0] MinRows=[3616] MaxRows=[4096] Average_Rows=[4000]
Total_Rows: 统计表 d0 的存储在磁盘上行数 20000 行(该数值仅供参考,不是精确的行数。获得精确的行数需要使用 count 函数) Total_Rows统计表 d0 的存储在磁盘上行数 20000 行(该数值仅供参考,不是精确的行数。获得精确的行数需要使用 count 函数)
Inmem_Rows 存储在写缓存中的数据行数没有落盘0 行表示内存缓存中没有数据 Inmem_Rows 存储在写缓存中的数据行数没有落盘0 行表示内存缓存中没有数据
@ -247,7 +254,7 @@ Average_Rows 每个 BLOCK 中的平均行数,此时为 4000 行
_block_dist: Total_Tables=[1] Total_Files=[2] Total_Vgroups=[1] _block_dist: Total_Tables=[1] Total_Files=[2] Total_Vgroups=[1]
Total_Tables: 子表的个数,这里为 1 Total_Tables 子表的个数,这里为 1
Total_Files 表数据被分别保存的数据文件数量,这里是 2 个文件 Total_Files 表数据被分别保存的数据文件数量,这里是 2 个文件
@ -281,7 +288,7 @@ Query OK, 24 row(s) in set (0.002444s)
</code></pre> </code></pre>
</details> </details>
上面是块中包含数据行数的块儿分布情况图,这里的 0100 0299 0498 … 表示的是每个块中包含的数据行数,上面的意思就是这个表的 5 个块,分布在 3483 ~3681 行的块有 1 个,占整个块的 20%,分布在 3881 ~ 4096最大行数的块数为 4 个,占整个块的 80% 其它区域内分布块数为 0。 上面是块中包含数据行数的块儿分布情况图,这里的 `0100 0299 0498 …` 表示的是每个块中包含的数据行数,上面的意思就是这个表的 5 个块,分布在 `3483 ~ 3681` 行的块有 1 个,占整个块的 20%,分布在 `3881 ~ 4096`(最大行数)的块数为 4 个,占整个块的 80% 其它区域内分布块数为 0。
需要注意,这里只会显示 data 文件中数据块的信息stt 文件中的数据的信息不会被显示。 需要注意,这里只会显示 data 文件中数据块的信息stt 文件中的数据的信息不会被显示。
@ -309,7 +316,7 @@ SHOW TRANSACTIONS;
SHOW TRANSACTION [tranaction_id]; SHOW TRANSACTION [tranaction_id];
``` ```
显示当前系统中正在执行的所有或者某一个事务的信息(该事务仅针对除普通表以外的元数据级别) 显示当前系统中正在执行的所有或者某一个事务的信息(该事务仅针对除普通表以外的元数据级别)
## SHOW USERS ## SHOW USERS

View File

@ -18,7 +18,7 @@ CREATE USER user_name PASS 'password' [SYSINFO {1|0}] [CREATEDB {1|0}];
`SYSINFO` 表示该用户是否能够查看系统信息。`1` 表示可以查看,`0` 表示无权查看。系统信息包括服务配置、dnode、vnode、存储等信息。缺省值为 `1` `SYSINFO` 表示该用户是否能够查看系统信息。`1` 表示可以查看,`0` 表示无权查看。系统信息包括服务配置、dnode、vnode、存储等信息。缺省值为 `1`
`CREATEDB` 表示该用户是否能够创建数据库。`1` 表示可以创建,`0` 表示无权创建。缺省值为 `0`// TDengine 企业版 3.3.2.0 开始支持 `CREATEDB` 表示该用户是否能够创建数据库。`1` 表示可以创建,`0` 表示无权创建。缺省值为 `0`。从企业版 v3.3.2.0 开始支持
在下面的示例中,我们创建一个密码为 `abc123!@#` 且可以查看系统信息的用户。 在下面的示例中,我们创建一个密码为 `abc123!@#` 且可以查看系统信息的用户。
@ -76,12 +76,12 @@ alter_user_clause: {
} }
``` ```
- PASS: 修改密码,后跟新密码 - PASS修改密码,后跟新密码
- ENABLE: 启用或禁用该用户,`1` 表示启用,`0` 表示禁用 - ENABLE启用或禁用该用户,`1` 表示启用,`0` 表示禁用
- SYSINFO: 允许或禁止查看系统信息,`1` 表示允许,`0` 表示禁止 - SYSINFO允许或禁止查看系统信息,`1` 表示允许,`0` 表示禁止
- CREATEDB: 允许或禁止创建数据库,`1` 表示允许,`0` 表示禁止。// TDengine 企业版 3.3.2.0 开始支持 - CREATEDB允许或禁止创建数据库,`1` 表示允许,`0` 表示禁止。从企业版 v3.3.2.0 开始支持
下面的示例禁用了名为 `test` 的用户: 下面的示例禁用了名为 `test` 的用户
```sql ```sql
taos> alter user test enable 0; taos> alter user test enable 0;

View File

@ -3,7 +3,7 @@ toc_max_heading_level: 4
title: 权限管理 title: 权限管理
--- ---
TDengine 中的权限管理分为[用户管理](../user)、数据库授权管理以及消息订阅授权管理,本节重点说明数据库授权和订阅授权。 TDengine 中的权限管理分为 [用户管理](../user)、数据库授权管理以及消息订阅授权管理,本节重点说明数据库授权和订阅授权。
授权管理仅在 TDengine 企业版中可用,请联系 TDengine 销售团队。授权语法在社区版可用,但不起作用。 授权管理仅在 TDengine 企业版中可用,请联系 TDengine 销售团队。授权语法在社区版可用,但不起作用。
## 数据库访问授权 ## 数据库访问授权
@ -33,19 +33,18 @@ priv_level : {
对数据库的访问权限包含读和写两种权限,它们可以被分别授予,也可以被同时授予。 对数据库的访问权限包含读和写两种权限,它们可以被分别授予,也可以被同时授予。
说明 说明
- priv_level 格式中 "." 之前为数据库名称,"." 之后为表名称,意思为表级别的授权控制。如果 "." 之后为 "\*",意为 "." 前所指定的数据库中的所有表
- priv_level 格式中 "." 之前为数据库名称, "." 之后为表名称,意思为表级别的授权控制。如果 "." 之后为 "\*" ,意为 "." 前所指定的数据库中的所有表 - "dbname.\*" 意思是名为 "dbname" 的数据库中的所有表
- "dbname.\*" 意思是名为 "dbname" 的数据库中的所有表 - "\*.\*" 意思是所有数据库名中的所有表
- "\*.\*" 意思是所有数据库名中的所有表
### 数据库权限说明 ### 数据库权限说明
对 root 用户和普通用户的权限的说明如下表 对 root 用户和普通用户的权限的说明如下表
| 用户 | 描述 | 权限说明 | | 用户 | 描述 | 权限说明 |
| -------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -------- | --------------------------------- | -- |
| 超级用户 | 只有 root 是超级用户 | DB 外部 所有操作权限例如user、dnode、udf、qnode等的CRUD DB 权限,包括 创建 删除 更新,例如修改 Option移动 Vgruop等 读 写 Enable/Disable 用户 | | 超级用户 | 只有 root 是超级用户 |<br/>DB 外部:所有操作权限,例如 user、dnode、udf、qnode 等的 CRUD <br/>DB 权限:包括创建、删除、修改 Option、移动 Vgruop、读、写、Enable/Disable 用户 |
| 普通用户 | 除 root 以外的其它用户均为普通用户 | 在可读的 DB 中,普通用户可以进行读操作 select describe show subscribe 在可写 DB 的内部,用户可以进行写操作: 创建、删除、修改 超级表 创建、删除、修改 子表 创建、删除、修改 topic 写入数据 被限制系统信息时,不可进行如下操作 show dnode、mnode、vgroups、qnode、snode 修改用户包括自身密码 show db时只能看到自己的db并且不能看到vgroups、副本、cache等信息 无论是否被限制系统信息,都可以 管理 udf 可以创建 DB 自己创建的 DB 具备所有权限 非自己创建的 DB ,参照读、写列表中的权限 | | 普通用户 | 除 root 以外的其它用户均为普通用户 | <br/>在可读的 DB 中:普通用户可以进行读操作 select、describe、show、subscribe <br/>在可写 DB 的内部,用户可以进行写操作,创建、删除、修改超级表,创建、删除、修改子表,创建、删除、修改 topic。写入数据 <br/>被限制系统信息时,不可进行如下操作 show dnode、mnode、vgroups、qnode、snode、修改用户包括自身密码、`show db` 时只能看到自己的 db并且不能看到 vgroups、副本、cache等信息 <br/>无论是否被限制系统信息,都可以管理 udf可以创建 DB、自己创建的 DB 具备所有权限、非自己创建的 DB,参照读、写列表中的权限 |
## 消息订阅授权 ## 消息订阅授权
@ -61,7 +60,7 @@ REVOKE SUBSCRIBE ON topic_name FROM user_name
## 基于标签的授权(表级授权) ## 基于标签的授权(表级授权)
TDengine 3.0.5.0 开始,我们支持按标签授权某个超级表中部分特定的子表。具体的 SQL 语法如下。 v3.0.5.0 开始,我们支持按标签授权某个超级表中部分特定的子表。具体的 SQL 语法如下。
```sql ```sql
GRANT privileges ON priv_level [WITH tag_condition] TO user_name GRANT privileges ON priv_level [WITH tag_condition] TO user_name
@ -110,11 +109,11 @@ priv_level : {
下表列出了在不同的数据库授权和表级授权的组合下产生的实际权限。 下表列出了在不同的数据库授权和表级授权的组合下产生的实际权限。
| | **表无授权** | **表读授权** | **表读授权有标签条件** | **表写授权** | **表写授权有标签条件** | | | **表无授权** | **表读授权** | **表读授权有标签条件** | **表写授权** | **表写授权有标签条件** |
| ---------------- | ---------------- | ---------------------------------------- | ------------------------------------------------------------ | ---------------------------------------- | ---------------------------------------------------------- | | -------------- | ------------- | --------------------------------- | ------------------------------------------------- | ---------------------------------- | -------------------- |
| **数据库无授权** | 无授权 | 对此表有读权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表无权限 | 对此表有写权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有写权限,对数据库下的其他表无权限 | | **数据库无授权** | 无授权 | 对此表有读权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表无权限 | 对此表有写权限,对数据库下的其他表无权限 | 对此表符合标签权限的子表有写权限,对数据库下的其他表无权限 |
| **数据库读授权** | 对所有表有读权限 | 对所有表有读权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表有读权限 | 对此表有写权限,对所有表有读权限 | 对此表符合标签权限的子表有写权限,所有表有读权限 | | **数据库读授权** | 对所有表有读权限 | 对所有表有读权限 | 对此表符合标签权限的子表有读权限,对数据库下的其他表有读权限 | 对此表有写权限,对所有表有读权限 | 对此表符合标签权限的子表有写权限,所有表有读权限 |
| **数据库写授权** | 对所有表有写权限 | 对此表有读权限,对所有表有写权限 | 对此表符合标签权限的子表有读权限,对所有表有写权限 | 对所有表有写权限 | 对此表符合标签权限的子表有写权限,数据库下的其他表有写权限 | | **数据库写授权** | 对所有表有写权限 | 对此表有读权限,对所有表有写权限 | 对此表符合标签权限的子表有读权限,对所有表有写权限 | 对所有表有写权限 | 对此表符合标签权限的子表有写权限,数据库下的其他表有写权限 |
## 查看用户授权 ## 查看用户授权
@ -127,7 +126,7 @@ show user privileges
## 撤销授权 ## 撤销授权
1. 撤销数据库访问的授权 1. 撤销数据库访问的授权
```sql ```sql
REVOKE privileges ON priv_level FROM user_name REVOKE privileges ON priv_level FROM user_name
@ -149,7 +148,7 @@ priv_level : {
} }
``` ```
2. 撤销数据订阅的授权 2. 撤销数据订阅的授权
```sql ```sql
REVOKE privileges ON priv_level FROM user_name REVOKE privileges ON priv_level FROM user_name

View File

@ -4,10 +4,10 @@ title: 自定义函数
description: 使用 UDF 的详细指南 description: 使用 UDF 的详细指南
--- ---
除了 TDengine 的内置函数以外用户还可以编写自己的函数逻辑并加入TDengine系统中。 除了 TDengine 的内置函数以外,用户还可以编写自己的函数逻辑并加入 TDengine 系统中。
## 创建 UDF ## 创建 UDF
用户可以通过 SQL 指令在系统中加载客户端所在主机上的 UDF 函数库(不能通过 RESTful 接口或 HTTP 管理界面来进行这一过程)。一旦创建成功,则当前 TDengine 集群的所有用户都可以在 SQL 指令中使用这些函数。UDF 存储在系统的 MNode 节点上,因此即使重启 TDengine 系统,已经创建的 UDF 也仍然可用。 用户可以通过 SQL 指令在系统中加载客户端所在主机上的 UDF 函数库(不能通过 RESTful 接口或 HTTP 管理界面来进行这一过程)。一旦创建成功,则当前 TDengine 集群的所有用户都可以在 SQL 指令中使用这些函数。UDF 存储在系统的 mnode 节点上,因此即使重启 TDengine 系统,已经创建的 UDF 也仍然可用。
在创建 UDF 时,需要区分标量函数和聚合函数。如果创建时声明了错误的函数类别,则可能导致通过 SQL 指令调用函数时出错。此外,用户需要保证输入数据类型与 UDF 程序匹配UDF 输出数据类型与 OUTPUTTYPE 匹配。 在创建 UDF 时,需要区分标量函数和聚合函数。如果创建时声明了错误的函数类别,则可能导致通过 SQL 指令调用函数时出错。此外,用户需要保证输入数据类型与 UDF 程序匹配UDF 输出数据类型与 OUTPUTTYPE 匹配。
@ -15,11 +15,11 @@ description: 使用 UDF 的详细指南
```sql ```sql
CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_type [LANGUAGE 'C|Python']; CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_type [LANGUAGE 'C|Python'];
``` ```
- OR REPLACE: 如果函数已经存在,会修改已有的函数属性。 - OR REPLACE如果函数已经存在,会修改已有的函数属性。
- function_name标量函数未来在 SQL 中被调用时的函数名 - function_name标量函数未来在 SQL 中被调用时的函数名
- LANGUAGE 'C|Python':函数编程语言,目前支持C语言和Python语言。 如果这个从句忽略编程语言是C语言 - LANGUAGE 'C|Python':函数编程语言,目前支持 C 语言和 Python 语言。如果这个从句忽略,编程语言是 C 语言。
- library_path如果编程语言是C路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件。如果编程语言是Python路径是包含 UDF 函数实现的Python文件路径。这个路径需要用英文单引号或英文双引号括起来 - library_path如果编程语言是C路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件)。如果编程语言是 Python路径是包含 UDF 函数实现的 Python 文件路径。这个路径需要用英文单引号或英文双引号括起来;
- output_type此函数计算结果的数据类型名称 - output_type此函数计算结果的数据类型名称
例如,如下语句可以把 libbitand.so 创建为系统中可用的 UDF 例如,如下语句可以把 libbitand.so 创建为系统中可用的 UDF
@ -36,19 +36,19 @@ CREATE [OR REPLACE] FUNCTION function_name AS library_path OUTPUTTYPE output_typ
```sql ```sql
CREATE [OR REPLACE] AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ] [LANGUAGE 'C|Python']; CREATE [OR REPLACE] AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ] [LANGUAGE 'C|Python'];
``` ```
- OR REPLACE: 如果函数已经存在,会修改已有的函数属性。 - OR REPLACE如果函数已经存在,会修改已有的函数属性。
- function_name聚合函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致; - function_name聚合函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
- LANGUAGE 'C|Python'函数编程语言目前支持C语言和Python语言v3.7+)。 - LANGUAGE 'C|Python':函数编程语言,目前支持 C 语言和 Python 语言v3.7+)。
- library_path如果编程语言是C路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件。如果编程语言是Python路径是包含 UDF 函数实现的Python文件路径。这个路径需要用英文单引号或英文双引号括起来 - library_path如果编程语言是C路径是包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 `.so` 文件)。如果编程语言是 Python路径是包含 UDF 函数实现的 Python 文件路径。这个路径需要用英文单引号或英文双引号括起来;
- output_type此函数计算结果的数据类型名称 - output_type此函数计算结果的数据类型名称
- buffer_size中间计算结果的缓冲区大小单位是字节。如果不使用可以不设置。 - buffer_size中间计算结果的缓冲区大小单位是字节。如果不使用可以不设置。
例如,如下语句可以把 libl2norm.so 创建为系统中可用的 UDF 例如,如下语句可以把 libl2norm.so 创建为系统中可用的 UDF
```sql ```sql
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8; CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8;
``` ```
例如,使用以下语句可以修改已经定义的 l2norm 函数的缓冲区大小为64。 例如,使用以下语句可以修改已经定义的 l2norm 函数的缓冲区大小为 64。
```sql ```sql
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 64; CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 64;
``` ```
@ -57,25 +57,26 @@ CREATE [OR REPLACE] AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE
## 管理 UDF ## 管理 UDF
- 删除指定名称的用户定义函数 - 删除指定名称的用户定义函数
``` ```
DROP FUNCTION function_name; DROP FUNCTION function_name;
``` ```
- function_name此参数的含义与 CREATE 指令中的 function_name 参数一致,也即要删除的函数的名字,例如bit_and, l2norm - function_name此参数的含义与 CREATE 指令中的 function_name 参数一致,也即要删除的函数的名字,例如 bit_and、l2norm
```sql ```sql
DROP FUNCTION bit_and; DROP FUNCTION bit_and;
``` ```
- 显示系统中当前可用的所有 UDF
- 显示系统中当前可用的所有 UDF。
```sql ```sql
SHOW FUNCTIONS; SHOW FUNCTIONS;
``` ```
## 调用 UDF ## 调用 UDF
在 SQL 指令中,可以直接以在系统中创建 UDF 时赋予的函数名来调用用户定义函数。例如: 在 SQL 指令中,可以直接以在系统中创建 UDF 时赋予的函数名来调用用户定义函数。
```sql ```sql
SELECT bit_and(c1,c2) FROM table; SELECT bit_and(c1,c2) FROM table;
``` ```
表示对表 table 上名为 c1, c2 的数据列调用名为 bit_and 的用户定义函数。SQL 指令中用户定义函数可以配合 WHERE 等查询特性来使用。 表示对表 table 上名为 c1c2 的数据列调用名为 bit_and 的用户定义函数。SQL 指令中用户定义函数可以配合 WHERE 等查询特性来使用。

View File

@ -4,36 +4,38 @@ title: 窗口预聚集
description: 窗口预聚集使用说明 description: 窗口预聚集使用说明
--- ---
在大数据量场景下, 经常需要查询某段时间内的汇总结果, 当历史数据变多或者时间范围变大时, 查询时间也会相应增加. 通过预聚集的方式可以将计算结果提前存储下来, 后续查询可以直接读取聚集结果, 而不需要扫描原始数据, 如当前Block内的SMA (Small Materialized Aggregates)信息. 在大数据量场景下,经常需要查询某段时间内的汇总结果,当历史数据变多或者时间范围变大时,查询时间也会相应增加。通过预聚集的方式可以将计算结果提前存储下来,后续查询可以直接读取聚集结果,而不需要扫描原始数据,如当前 Block 内的 SMA (Small Materialized Aggregates)信息。
Block内的SMA信息粒度较小, 若查询时间范围是日,月甚至年时, Block的数量将会很多, 因此TSMA (Time-Range Small Materialized Aggregates)支持用户指定时间窗口进行预聚集. 通过对固定时间窗口内的数据进行预计算, 并将计算结果存储下来, 查询时通过查询预计算结果以提高查询性能。
Block 内的 SMA 信息粒度较小,若查询时间范围是日,月甚至年时Block 的数量将会很多,因此 TSMA (Time-Range Small Materialized Aggregates)支持用户指定时间窗口进行预聚集。通过对固定时间窗口内的数据进行预计算,并将计算结果存储下来,查询时通过查询预计算结果以提高查询性能。
![TSMA Introduction](./pic/TSMA_intro.png) ![TSMA Introduction](./pic/TSMA_intro.png)
## 创建TSMA ## 创建 TSMA
```sql ```sql
-- 创建基于超级表或普通表的tsma -- 创建基于超级表或普通表的 tsma
CREATE TSMA tsma_name ON [dbname.]table_name FUNCTION (func_name(func_param) [, ...] ) INTERVAL(time_duration); CREATE TSMA tsma_name ON [dbname.]table_name FUNCTION (func_name(func_param) [, ...] ) INTERVAL(time_duration);
-- 创建基于小窗口tsma的大窗口tsma
-- 创建基于小窗口 tsma 的大窗口 tsma
CREATE RECURSIVE TSMA tsma_name ON [db_name.]tsma_name1 INTERVAL(time_duration); CREATE RECURSIVE TSMA tsma_name ON [db_name.]tsma_name1 INTERVAL(time_duration);
time_duration: time_duration:
number unit number unit
``` ```
创建 TSMA 时需要指定 TSMA 名字, 表名字, 函数列表以及窗口大小. 当基于一个已经存在的 TSMA 创建新的 TSMA 时, 需要使用 `RECURSIVE` 关键字但不能指定 `FUNCTION()` 新创建的 TSMA 已有 TSMA 拥有相同的函数列表, 且此种情况下所指定的 INTERVAL 必须至少为所基于的 TSMA 窗口长度的整数倍, 并且天不能基于2h或3h建立, 只能基于1h建立, 月也只能基于1d而非2d,3d建立。 创建 TSMA 时需要指定 TSMA 名字,表名字,函数列表以及窗口大小。当基于一个已经存在的 TSMA 创建新的 TSMA 时,需要使用 `RECURSIVE` 关键字但不能指定 `FUNCTION()`,新创建的 TSMA 已有 TSMA 拥有相同的函数列表,且此种情况下所指定的 INTERVAL 必须至少为所基于的 TSMA 窗口长度的整数倍,并且天不能基于 2h 或 3h 建立,只能基于 1h 建立,月也只能基于 1d 而非 2d、3d 建立。
其中 TSMA 命名规则与表名字类似, 长度最大限制为表名长度限制减去输出表后缀长度, 表名长度限制为193, 输出表后缀为`_tsma_res_stb_`, TSMA 名字最大长度为178. 其中 TSMA 命名规则与表名字类似,长度最大限制为表名长度限制减去输出表后缀长度,表名长度限制为 193输出表后缀为`_tsma_res_stb_`TSMA 名字最大长度为 178。
TSMA只能基于超级表和普通表创建, 不能基于子表创建. TSMA 只能基于超级表和普通表创建,不能基于子表创建。
函数列表中只能指定支持的聚集函数(见下文), 并且函数参数必须为1个, 即使当前函数支持多个参数, 函数参数内必须为普通列名, 不能为标签列. 函数列表中完全相同的函数和列会被去重, 如同时创建两个avg(c1), 则只会计算一个输出. TSMA 计算时将会把所有`函数中间结果`都输出到另一张超级表中, 输出超级表还包含了原始表的所有tag列. 函数列表中函数个数最多支持创建表最大列个数(包括tag列)减去 TSMA 计算附加的四列, 分别为`_wstart`, `_wend`, `_wduration`, 以及一个新增tag列 `tbname`, 再减去原始表的tag列数. 若列个数超出限制, 会报`Too many columns`错误. 函数列表中只能指定支持的聚集函数(见下文),并且函数参数必须为 1 个,即使当前函数支持多个参数,函数参数内必须为普通列名,不能为标签列。函数列表中完全相同的函数和列会被去重,如同时创建两个 avg(c1)则只会计算一个输出。TSMA 计算时将会把所有 `函数中间结果` 都输出到另一张超级表中,输出超级表还包含了原始表的所有 tag 列。函数列表中函数个数最多支持创建表最大列个数(包括 tag 列)减去 TSMA 计算附加的四列,分别为 `_wstart`、`_wend`、`_wduration`,以及一个新增 tag 列 `tbname`,再减去原始表的 tag 列数。若列个数超出限制,会报 `Too many columns` 错误。
由于TSMA输出为一张超级表, 因此输出表的行长度受最大行长度限制, 不同函数的`中间结果`大小各异, 一般都大于原始数据大小, 若输出表的行长度大于最大行长度限制, 将会报`Row length exceeds max length`错误. 此时需要减少函数个数或者将常用的函数进行分组拆分到多个TSMA中. 由于 TSMA 输出为一张超级表,因此输出表的行长度受最大行长度限制,不同函数的 `中间结果` 大小各异,一般都大于原始数据大小,若输出表的行长度大于最大行长度限制,将会报 `Row length exceeds max length` 错误。此时需要减少函数个数或者将常用的函数进行分组拆分到多个 TSMA 中。
窗口大小的限制为[1m ~ 1y/12n]. INTERVAL 的单位与查询中INTERVAL子句相同, 如 a (毫秒), b (纳秒), h (小时), m (分钟), s (秒), u (微秒), d (天), w(周), n(月), y(年). 窗口大小的限制为 [1m ~ 1y/12n]。INTERVAL 的单位与查询中 INTERVAL 子句相同,如 a(毫秒)、b(纳秒)、h(小时)、m(分钟)、s(秒)、u(微秒)、d(天)、w(周)、n(月)、y(年)。
TSMA为库内对象, 但名字全局唯一. 集群内一共可创建TSMA个数受参数`maxTsmaNum`限制, 参数默认值为3, 范围: [0-3]. 注意, 由于TSMA后台计算使用流计算, 因此每创建一条TSMA, 将会创建一条流, 因此能够创建的TSMA条数也受当前已经存在的流条数和最大可创建流条数限制. TSMA 为库内对象,但名字全局唯一。集群内一共可创建 TSMA 个数受参数 `maxTsmaNum` 限制,参数默认值为 3范围[0-3]。注意,由于 TSMA 后台计算使用流计算,因此每创建一条 TSMA将会创建一条流因此能够创建的 TSMA 条数也受当前已经存在的流条数和最大可创建流条数限制。
## 支持的函数列表 ## 支持的函数列表
| 函数| 备注 | | 函数| 备注 |
@ -44,65 +46,64 @@ TSMA为库内对象, 但名字全局唯一. 集群内一共可创建TSMA个数
|first|| |first||
|last|| |last||
|avg|| |avg||
|count| 若想使用count(*), 则应创建count(ts)函数| |count| 若想使用 count(*),则应创建 count(ts) 函数|
|spread|| |spread||
|stddev|| |stddev||
||| |||
## 删除TSMA ## 删除 TSMA
```sql ```sql
DROP TSMA [db_name.]tsma_name; DROP TSMA [db_name.]tsma_name;
``` ```
若存在其他TSMA基于当前被删除TSMA创建, 则删除操作报`Invalid drop base tsma, drop recursive tsma first`错误. 因此需先删除 所有Recursive TSMA. 若存在其他 TSMA 基于当前被删除 TSMA 创建,则删除操作报 `Invalid drop base tsma, drop recursive tsma first` 错误。因此需先删除 所有 Recursive TSMA。
## TSMA的计算 ## TSMA 的计算
TSMA的计算结果为与原始表相同库下的一张超级表, 此表用户不可见. 不可删除, 在`DROP TSMA`时自动删除. TSMA的计算是通过流计算完成的, 此过程为后台异步过程, TSMA的计算结果不保证实时性, 但可以保证最终正确性. TSMA 的计算结果为与原始表相同库下的一张超级表,此表用户不可见。不可删除,在 `DROP TSMA` 时自动删除。TSMA 的计算是通过流计算完成的此过程为后台异步过程TSMA 的计算结果不保证实时性,但可以保证最终正确性。
TSMA计算时若原始子表内没有数据, 则可能不会创建对应的输出子表, 因此在count查询中, 即使配置了`countAlwaysReturnValue`, 也不会返回该表的结果. TSMA 计算时若原始子表内没有数据,则可能不会创建对应的输出子表,因此在 count 查询中,即使配置了 `countAlwaysReturnValue`,也不会返回该表的结果。
当存在大量历史数据时, 创建TSMA之后, 流计算将会首先计算历史数据, 此期间新创建的TSMA不会被使用. 数据更新删除或者过期数据到来时自动重新计算影响部分数据。 在重新计算期间 TSMA 查询结果不保证实时性。若希望查询实时数据, 可以通过在 SQL 中添加 hint `/*+ skip_tsma() */` 或者关闭参数`querySmaOptimize`从原始数据查询。 当存在大量历史数据时,创建 TSMA 之后,流计算将会首先计算历史数据,此期间新创建的 TSMA 不会被使用。数据更新删除或者过期数据到来时自动重新计算影响部分数据。在重新计算期间 TSMA 查询结果不保证实时性。若希望查询实时数据,可以通过在 SQL 中添加 hint `/*+ skip_tsma() */` 或者关闭参数 `querySmaOptimize` 从原始数据查询。
## TSMA的使用与限制 ## TSMA 的使用与限制
客户端配置参数: `querySmaOptimize`, 用于控制查询时是否使用TSMA, `True`为使用, `False`为不使用即从原始数据查询. - 客户端配置参数:`querySmaOptimize`用于控制查询时是否使用TSMA`True`为使用,`False` 为不使用即从原始数据查询。
- 客户端配置参数:`maxTsmaCalcDelay`,单位为秒,用于控制用户可以接受的 TSMA 计算延迟,若 TSMA 的计算进度与最新时间差距在此范围内,则该 TSMA 将会被使用若超出该范围则不使用默认值60010 分钟最小值60010 分钟最大值864001 天)。
- 客户端配置参数:`tsmaDataDeleteMark`,单位毫秒,与流计算参数 `deleteMark` 一致,用于控制流计算中间结果的保存时间,默认值为 1d最小值为 1h。因此那些距最后一条数据时间大于配置参数的历史数据将不保存流计算中间结果因此若修改这些时间窗口内的数据TSMA 的计算结果中将不包含更新的结果。即与查询原始数据结果将不一致。
客户端配置参数:`maxTsmaCalcDelay`,单位 s用于控制用户可以接受的 TSMA 计算延迟,若 TSMA 的计算进度与最新时间差距在此范围内, 则该 TSMA 将会被使用, 若超出该范围, 则不使用, 默认值: 60010 分钟), 最小值: 60010 分钟), 最大值: 864001 天). ### 查询时使用 TSMA
客户端配置参数: `tsmaDataDeleteMark`, 单位毫秒, 与流计算参数`deleteMark`一致, 用于控制流计算中间结果的保存时间, 默认值为: 1d, 最小值为1h. 因此那些距最后一条数据时间大于配置参数的历史数据将不保存流计算中间结果, 因此若修改这些时间窗口内的数据, TSMA的计算结果中将不包含更新的结果. 即与查询原始数据结果将不一致. 已在 TSMA 中定义的 agg 函数在大部分查询场景下都可直接使用,若存在多个可用的 TSMA优先使用大窗口的 TSMA未闭合窗口通过查询小窗口 TSMA 或者原始数据计算。同时也有某些场景不能使用 TSMA(见下文)。不可用时整个查询将使用原始数据进行计算。
### 查询时使用TSMA 未指定窗口大小的查询语句默认优先使用包含所有查询聚合函数的最大窗口 TSMA 进行数据的计算。如 `SELECT COUNT(*) FROM stable GROUP BY tbname` 将会使用包含 count(ts) 且窗口最大的 TSMA。因此若使用聚合查询频率高时应当尽可能创建大窗口的 TSMA。
已在 TSMA 中定义的 agg 函数在大部分查询场景下都可直接使用, 若存在多个可用的 TSMA 优先使用大窗口的 TSMA 未闭合窗口通过查询小窗口TSMA或者原始数据计算。 同时也有某些场景不能使用 TSMA(见下文)。 不可用时整个查询将使用原始数据进行计算。 指定窗口大小时即 `INTERVAL` 语句,使用最大的可整除窗口 TSMA。窗口查询中`INTERVAL` 的窗口大小、`OFFSET` 以及 `SLIDING` 都影响能使用的 TSMA 窗口大小。因此若使用窗口查询较多时,需要考虑经常查询的窗口大小,以及 offset、sliding 大小来创建 TSMA。
未指定窗口大小的查询语句默认优先使用包含所有查询聚合函数的最大窗口 TSMA 进行数据的计算。 如`SELECT COUNT(*) FROM stable GROUP BY tbname`将会使用包含count(ts)且窗口最大的TSMA。因此若使用聚合查询频率高时, 应当尽可能创建大窗口的TSMA. 例如 创建 TSMA 窗口大小 `5m` 一条,`10m` 一条,查询时 `INTERVAL(30m)`,那么优先使用 `10m` 的 TSMA若查询为 `INTERVAL(30m, 10m) SLIDING(5m)`,那么仅可使用 `5m` 的 TSMA 查询。
指定窗口大小时即 `INTERVAL` 语句,使用最大的可整除窗口 TSMA。 窗口查询中, `INTERVAL` 的窗口大小, `OFFSET` 以及 `SLIDING` 都影响能使用的 TSMA 窗口大小, 可整 除窗口 TSMA 即 TSMA 窗口大小可被查询语句的 `INTERVAL OFFSET SLIDING` 整除的窗口。因此若使用窗口查询较多时, 需要考虑经常查询的窗口大小, 以及 offset, sliding大小来创建TSMA.
例 1. 如 创建 TSMA 窗口大小 `5m` 一条, `10m` 一条, 查询时 `INTERVAL(30m)` 那么优先使用 `10m` 的 TSMA 若查询为 `INTERVAL(30m, 10m) SLIDING(5m)` 那么仅可使用 `5m` 的 TSMA 查询。
### 查询限制 ### 查询限制
在开启了参数`querySmaOptimize`并且无`skip_tsma()` hint时, 以下查询场景无法使用TSMA: 在开启了参数 `querySmaOptimize` 并且无 `skip_tsma()` hint 时,以下查询场景无法使用 TSMA。
- 某个TSMA 中定义的 agg 函数不能覆盖当前查询的函数列表时 - 某个 TSMA 中定义的 agg 函数不能覆盖当前查询的函数列表时
- 非 `INTERVAL` 的其他窗口,或者 `INTERVAL` 查询窗口大小(包括 `INTERVALSLIDINGOFFSET`)不是定义窗口的整数倍,如定义窗口为 2m查询使用 5 分钟窗口,但若存在 1m 的窗口,则可以使用。 - 非 `INTERVAL` 的其他窗口,或者 `INTERVAL` 查询窗口大小(包括 `INTERVALSLIDINGOFFSET`)不是定义窗口的整数倍,如定义窗口为 2m查询使用 5 分钟窗口,但若存在 1m 的窗口,则可以使用。
- 查询 `WHERE` 条件中包含任意普通列(非主键时间列)的过滤。 - 查询 `WHERE` 条件中包含任意普通列(非主键时间列)的过滤。
- `PARTITION` 或者 `GROUY BY` 包含任意普通列或其表达式时 - `PARTITION` 或者 `GROUY BY` 包含任意普通列或其表达式时
- 可以使用其他更快的优化逻辑时, 如last cache优化, 若符合last优化的条件, 则先走last 优化, 无法走last时, 再判断是否可以走tsma优化 - 可以使用其他更快的优化逻辑时,如 last cache 优化,若符合 last 优化的条件,则先走 last 优化,无法走 last 时,再判断是否可以走 tsma 优化
- 当前 TSMA 计算进度延迟大于配置参数 `maxTsmaCalcDelay` - 当前 TSMA 计算进度延迟大于配置参数 `maxTsmaCalcDelay`
下面是一些例子: 下面是一些例子
```sql ```sql
SELECT agg_func_list [, pesudo_col_list] FROM stable WHERE exprs [GROUP/PARTITION BY [tbname] [, tag_list]] [HAVING ...] [INTERVAL(time_duration, offset) SLIDING(duration)]...; SELECT agg_func_list [, pesudo_col_list] FROM stable WHERE exprs [GROUP/PARTITION BY [tbname] [, tag_list]] [HAVING ...] [INTERVAL(time_duration, offset) SLIDING(duration)]...;
-- 创建 -- 创建
CREATE TSMA tsma1 ON stable FUNCTION(COUNT(ts), SUM(c1), SUM(c3), MIN(c1), MIN(c3), AVG(c1)) INTERVAL(1m); CREATE TSMA tsma1 ON stable FUNCTION(COUNT(ts), SUM(c1), SUM(c3), MIN(c1), MIN(c3), AVG(c1)) INTERVAL(1m);
-- 查询 -- 查询
SELECT COUNT(*), SUM(c1) + SUM(c3) FROM stable; ---- use tsma1 SELECT COUNT(*), SUM(c1) + SUM(c3) FROM stable; ---- use tsma1
SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma1 SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma1
SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h); ---use tsma1 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h); --- use tsma1
SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- can't use, spread func not defined, although SPREAD can be calculated by MIN and MAX which are defined. SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- can't use, spread func not defined, although SPREAD can be calculated by MIN and MAX which are defined.
SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- can't use tsma1, time_duration not fit. Normally, query_time_duration should be multple of create_duration. SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- can't use tsma1, time_duration not fit. Normally, query_time_duration should be multple of create_duration.
SELECT COUNT(*), MIN(c1) FROM stable where c2 > 0; ---- can't use tsma1, can't do c2 filtering SELECT COUNT(*), MIN(c1) FROM stable where c2 > 0; ---- can't use tsma1, can't do c2 filtering
@ -113,10 +114,10 @@ SELECT MIN(c3), MIN(c2) FROM stable INTERVAL(1m); ---- can't use tsma1, c2 is no
CREATE RECURSIVE TSMA tsma2 on tsma1 INTERVAL(1h); CREATE RECURSIVE TSMA tsma2 on tsma1 INTERVAL(1h);
SELECT COUNT(*), SUM(c1) FROM stable; ---- use tsma2 SELECT COUNT(*), SUM(c1) FROM stable; ---- use tsma2
SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma2 SELECT COUNT(*), AVG(c1) FROM stable GROUP/PARTITION BY tbname, tag1, tag2; --- use tsma2
SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(2h); ---use tsma2 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(2h); --- use tsma2
SELECT COUNT(*), MIN(c1) FROM stable WHERE ts < '2023-01-01 10:10:10' INTERVAL(30m); --use tsma1 SELECT COUNT(*), MIN(c1) FROM stable WHERE ts < '2023-01-01 10:10:10' INTERVAL(30m); --use tsma1
SELECT COUNT(*), MIN(c1) + MIN(c3) FROM stable INTERVAL(30m); ---use tsma1 SELECT COUNT(*), MIN(c1) + MIN(c3) FROM stable INTERVAL(30m); --- use tsma1
SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h) SLIDING(30m); ---use tsma1 SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(1h) SLIDING(30m); --- use tsma1
SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- can't use tsma1 or tsma2, spread func not defined SELECT COUNT(*), MIN(c1), SPREAD(c1) FROM stable INTERVAL(1h); ----- can't use tsma1 or tsma2, spread func not defined
SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- can't use tsma1 or tsma2, time_duration not fit. Normally, query_time_duration should be multple of create_duration. SELECT COUNT(*), MIN(c1) FROM stable INTERVAL(30s); ----- can't use tsma1 or tsma2, time_duration not fit. Normally, query_time_duration should be multple of create_duration.
SELECT COUNT(*), MIN(c1) FROM stable where c2 > 0; ---- can't use tsma1 or tsam2, can't do c2 filtering SELECT COUNT(*), MIN(c1) FROM stable where c2 > 0; ---- can't use tsma1 or tsam2, can't do c2 filtering
@ -124,15 +125,15 @@ SELECT COUNT(*), MIN(c1) FROM stable where c2 > 0; ---- can't use tsma1 or tsam2
### 使用限制 ### 使用限制
创建TSMA之后, 对原始超级表的操作有以下限制: 创建 TSMA 之后,对原始超级表的操作有以下限制:
- 必须删除该表上的所有TSMA才能删除该表. - 必须删除该表上的所有 TSMA 才能删除该表。
- 原始表所有tag列不能删除, 也不能修改tag列名或子表的tag值, 必须先删除TSMA, 才能删除tag列. - 原始表所有 tag 列不能删除,也不能修改 tag 列名或子表的 tag 值,必须先删除 TSMA才能删除 tag 列。
- 若某些列被TSMA使用了, 则这些列不能被删除, 必须先删除TSMA. 添加列不受影响, 但是新添加的列不在任何TSMA中, 因此若要计算新增列, 需要新创建其他的TSMA. - 若某些列被 TSMA 使用了,则这些列不能被删除,必须先删除 TSMA。添加列不受影响但是新添加的列不在任何 TSMA 中,因此若要计算新增列,需要新创建其他的 TSMA。
## 查看TSMA ## 查看TSMA
```sql ```sql
SHOW [db_name.]TSMAS; SHOW [db_name.]TSMAS;
SELECT * FROM information_schema.ins_tsma; SELECT * FROM information_schema.ins_tsma;
``` ```
若创建时指定的较多的函数, 且列名较长, 在显示函数列表时可能会被截断(目前最大支持输出256KB). 若创建时指定的较多的函数,且列名较长,在显示函数列表时可能会被截断(目前最大支持输出 256KB)。

View File

@ -9,15 +9,15 @@ description: "TDengine 3.0 版本的语法变更说明"
| # | **元素** | **<div style={{width: 60}}>差异性</div>** | **说明** | | # | **元素** | **<div style={{width: 60}}>差异性</div>** | **说明** |
| - | :------- | :-------- | :------- | | - | :------- | :-------- | :------- |
| 1 | VARCHAR | 新增 | BINARY类型的别名。 | 1 | VARCHAR | 新增 | BINARY类型的别名。
| 2 | TIMESTAMP字面量 | 新增 | 新增支持 TIMESTAMP 'timestamp format' 语法。 | 2 | TIMESTAMP 字面量 | 新增 | 新增支持 TIMESTAMP 'timestamp format' 语法。
| 3 | _ROWTS伪列 | 新增 | 表示时间戳主键。是_C0伪列的别名。 | 3 | _ROWTS 伪列 | 新增 | 表示时间戳主键。是_C0伪列的别名。
| 4 | _IROWTS伪列 | 新增 | 用于返回 interp 函数插值结果对应的时间戳列。 | 4 | _IROWTS 伪列 | 新增 | 用于返回 interp 函数插值结果对应的时间戳列。
| 5 | INFORMATION_SCHEMA | 新增 | 包含各种SCHEMA定义的系统数据库。 | 5 | INFORMATION_SCHEMA | 新增 | 包含各种 SCHEMA 定义的系统数据库。
| 6 | PERFORMANCE_SCHEMA | 新增 | 包含运行信息的系统数据库。 | 6 | PERFORMANCE_SCHEMA | 新增 | 包含运行信息的系统数据库。
| 7 | 连续查询 | 废除 | 不再支持连续查询。相关的各种语法和接口废除。 | 7 | 连续查询 | 废除 | 不再支持连续查询。相关的各种语法和接口废除。
| 8 | 混合运算 | 增强 | 查询中的混合运算标量运算和矢量运算混合全面增强SELECT的各个子句均全面支持符合语法语义的混合运算。 | 8 | 混合运算 | 增强 | 查询中的混合运算标量运算和矢量运算混合全面增强SELECT 的各个子句均全面支持符合语法语义的混合运算。
| 9 | 标签运算 | 新增 |在查询中,标签列可以像普通列一样参与各种运算,用于各种子句。 | 9 | 标签运算 | 新增 |在查询中,标签列可以像普通列一样参与各种运算,用于各种子句。
| 10 | 时间线子句和时间函数用于超级表查询 | 增强 |没有PARTITION BY时超级表的数据会被合并成一条时间线。 | 10 | 时间线子句和时间函数用于超级表查询 | 增强 |没有 PARTITION BY 时,超级表的数据会被合并成一条时间线。
| 11 | GEOMETRY | 新增 | 几何类型。 | 11 | GEOMETRY | 新增 | 几何类型。
## SQL 语句变更 ## SQL 语句变更
@ -26,15 +26,15 @@ description: "TDengine 3.0 版本的语法变更说明"
| # | **语句** | **<div style={{width: 60}}>差异性</div>** | **说明** | | # | **语句** | **<div style={{width: 60}}>差异性</div>** | **说明** |
| - | :------- | :-------- | :------- | | - | :------- | :-------- | :------- |
| 1 | ALTER ACCOUNT | 废除 | 2.x中为企业版功能3.0不再支持。语法暂时保留执行报“This statement is no longer supported”错误。 | 1 | ALTER ACCOUNT | 废除 | 2.x 中为企业版功能3.0 不再支持。语法暂时保留,执行报 “This statement is no longer supported” 错误。
| 2 | ALTER ALL DNODES | 新增 | 修改所有DNODE的参数。 | 2 | ALTER ALL DNODES | 新增 | 修改所有 DNODE 的参数。
| 3 | ALTER DATABASE | 调整 | <p>废除</p><ul><li>QUORUM写入需要的副本确认数。3.0 版本默认行为是强一致性,且不支持修改为弱一致性。</li><li>BLOCKSVNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>UPDATE更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>CACHELAST缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>COMP3.0版本暂不支持修改。</li></ul><p>新增</p><ul><li>CACHEMODEL表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE表示缓存子表最近数据的内存大小。</li><li>WAL_FSYNC_PERIOD代替原FSYNC参数。</li><li>WAL_LEVEL代替原WAL参数。</li><li>WAL_RETENTION_PERIOD3.0.4.0版本新增wal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZE3.0.4.0版本新增wal文件的额外保留策略,用于数据订阅。</li></ul><p>调整</p><ul><li>KEEP3.0版本新增支持带单位的设置方式。</li></ul> | 3 | ALTER DATABASE | 调整 | <p>废除</p><ul><li>QUORUM写入需要的副本确认数。3.0 版本默认行为是强一致性,且不支持修改为弱一致性。</li><li>BLOCKSVNODE使用的内存块数。3.0 版本使用 BUFFER 来表示 VNODE 写入内存池的大小。</li><li>UPDATE更新操作的支持模式。3.0 版本所有数据库都支持部分列更新。</li><li>CACHELAST缓存最新一行数据的模式。3.0 版本用 CACHEMODEL 代替。</li><li>COMP3.0 版本暂不支持修改。</li></ul><p>新增</p><ul><li>CACHEMODEL表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE表示缓存子表最近数据的内存大小。</li><li>WAL_FSYNC_PERIOD代替原 FSYNC 参数。</li><li>WAL_LEVEL代替原 WAL 参数。</li><li>WAL_RETENTION_PERIODv3.0.4.0 新增WAL 文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZEv3.0.4.0 新增WAL 文件的额外保留策略,用于数据订阅。</li></ul><p>调整</p><ul><li>KEEP3.0 版本新增支持带单位的设置方式。</li></ul>
| 4 | ALTER STABLE | 调整 | 废除<ul><li>CHANGE TAG修改标签列的名称。3.0版本使用RENAME TAG代替。<br/>新增</li><li>RENAME TAG代替原CHANGE TAG子句。</li><li>COMMENT修改超级表的注释。</li></ul> | 4 | ALTER STABLE | 调整 | 废除<ul><li>CHANGE TAG修改标签列的名称。3.0 版本使用 RENAME TAG 代替。<br/>新增</li><li>RENAME TAG代替原 CHANGE TAG 子句。</li><li>COMMENT修改超级表的注释。</li></ul>
| 5 | ALTER TABLE | 调整 | 废除<ul><li>CHANGE TAG修改标签列的名称。3.0版本使用RENAME TAG代替。<br/>新增</li><li>RENAME TAG代替原CHANGE TAG子句。</li><li>COMMENT修改表的注释。</li><li>TTL修改表的生命周期。</li></ul> | 5 | ALTER TABLE | 调整 | 废除<ul><li>CHANGE TAG修改标签列的名称。3.0 版本使用 RENAME TAG 代替。<br/>新增</li><li>RENAME TAG代替原 CHANGE TAG 子句。</li><li>COMMENT修改表的注释。</li><li>TTL修改表的生命周期。</li></ul>
| 6 | ALTER USER | 调整 | 废除<ul><li>PRIVILEGE修改用户权限。3.0版本使用GRANT和REVOKE来授予和回收权限。<br/>新增</li><li>ENABLE启用或停用此用户。</li><li>SYSINFO修改用户是否可查看系统信息。</li></ul> | 6 | ALTER USER | 调整 | 废除<ul><li>PRIVILEGE修改用户权限。3.0 版本使用 GRANT REVOKE 来授予和回收权限。<br/>新增</li><li>ENABLE启用或停用此用户。</li><li>SYSINFO修改用户是否可查看系统信息。</li></ul>
| 7 | COMPACT VNODES | 暂不支持 | 整理指定VNODE的数据。3.0.0版本暂不支持。 | 7 | COMPACT VNODES | 暂不支持 | 整理指定 VNODE 的数据。
| 8 | CREATE ACCOUNT | 废除 | 2.x中为企业版功能3.0不再支持。语法暂时保留执行报“This statement is no longer supported”错误。 | 8 | CREATE ACCOUNT | 废除 | 2.x 中为企业版功能3.0 不再支持。语法暂时保留,执行报 “This statement is no longer supported” 错误。
| 9 | CREATE DATABASE | 调整 | <p>废除</p><ul><li>BLOCKSVNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHEVNODE使用的内存块的大小。3.0版本使用BUFFER来表示VNODE写入内存池的大小。</li><li>CACHELAST缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。</li><li>DAYS数据文件存储数据的时间跨度。3.0版本使用DURATION代替。</li><li>FSYNC当 WAL 设置为 2 时,执行 fsync 的周期。3.0版本使用WAL_FSYNC_PERIOD代替。</li><li>QUORUM写入需要的副本确认数。3.0版本使用STRICT来指定强一致还是弱一致。</li><li>UPDATE更新操作的支持模式。3.0版本所有数据库都支持部分列更新。</li><li>WALWAL 级别。3.0版本使用WAL_LEVEL代替。</li></ul><p>新增</p><ul><li>BUFFER一个 VNODE 写入内存池大小。</li><li>CACHEMODEL表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE表示缓存子表最近数据的内存大小。</li><li>DURATION代替原DAYS参数。新增支持带单位的设置方式。</li><li>PAGES一个 VNODE 中元数据存储引擎的缓存页个数。</li><li>PAGESIZE一个 VNODE 中元数据存储引擎的页大小。</li><li>RETENTIONS表示数据的聚合周期和保存时长。</li><li>STRICT表示数据同步的一致性要求。</li><li>SINGLE_STABLE表示此数据库中是否只可以创建一个超级表。</li><li>VGROUPS数据库中初始VGROUP的数目。</li><li>WAL_FSYNC_PERIOD代替原FSYNC参数。</li><li>WAL_LEVEL代替原WAL参数。</li><li>WAL_RETENTION_PERIODwal文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZEwal文件的额外保留策略,用于数据订阅。</li></ul><p>调整</p><ul><li>KEEP3.0版本新增支持带单位的设置方式。</li></ul> | 9 | CREATE DATABASE | 调整 | <p>废除</p><ul><li>BLOCKSVNODE 使用的内存块数。3.0 版本使用 BUFFER 来表示 VNODE 写入内存池的大小。</li><li>CACHEVNODE 使用的内存块的大小。3.0 版本使用 BUFFER 来表示 VNODE 写入内存池的大小。</li><li>CACHELAST缓存最新一行数据的模式。3.0 版本用 CACHEMODEL 代替。</li><li>DAYS数据文件存储数据的时间跨度。3.0 版本使用 DURATION 代替。</li><li>FSYNC当 WAL 设置为 2 时,执行 fsync 的周期。3.0 版本使用 WAL_FSYNC_PERIOD 代替。</li><li>QUORUM写入需要的副本确认数。3.0 版本使用 STRICT 来指定强一致还是弱一致。</li><li>UPDATE更新操作的支持模式。3.0 版本所有数据库都支持部分列更新。</li><li>WALWAL 级别。3.0 版本使用 WAL_LEVEL 代替。</li></ul><p>新增</p><ul><li>BUFFER一个 VNODE 写入内存池大小。</li><li>CACHEMODEL表示是否在内存中缓存子表的最近数据。</li><li>CACHESIZE表示缓存子表最近数据的内存大小。</li><li>DURATION代替原 DAYS 参数。新增支持带单位的设置方式。</li><li>PAGES一个 VNODE 中元数据存储引擎的缓存页个数。</li><li>PAGESIZE一个 VNODE 中元数据存储引擎的页大小。</li><li>RETENTIONS表示数据的聚合周期和保存时长。</li><li>STRICT表示数据同步的一致性要求。</li><li>SINGLE_STABLE表示此数据库中是否只可以创建一个超级表。</li><li>VGROUPS数据库中初始 VGROUP 的数目。</li><li>WAL_FSYNC_PERIOD代替原 FSYNC 参数。</li><li>WAL_LEVEL代替原 WAL 参数。</li><li>WAL_RETENTION_PERIODWAL 文件的额外保留策略,用于数据订阅。</li><li>WAL_RETENTION_SIZEWAL 文件的额外保留策略,用于数据订阅。</li></ul><p>调整</p><ul><li>KEEP3.0 版本新增支持带单位的设置方式。</li></ul>
| 10 | CREATE DNODE | 调整 | 新增主机名和端口号分开指定语法<ul><li>CREATE DNODE dnode_host_name PORT port_val</li></ul> | 10 | CREATE DNODE | 调整 | 新增主机名和端口号分开指定语法<ul><li>CREATE DNODE dnode_host_name PORT port_val</li></ul>
| 11 | CREATE INDEX | 新增 | 创建SMA索引。 | 11 | CREATE INDEX | 新增 | 创建SMA索引。
| 12 | CREATE MNODE | 新增 | 创建管理节点。 | 12 | CREATE MNODE | 新增 | 创建管理节点。
@ -43,7 +43,7 @@ description: "TDengine 3.0 版本的语法变更说明"
| 15 | CREATE STREAM | 新增 | 创建流。 | 15 | CREATE STREAM | 新增 | 创建流。
| 16 | CREATE TABLE | 调整 | 新增表参数语法<ul><li>COMMENT表注释。</li><li>WATERMARK指定窗口的关闭时间。</li><li>MAX_DELAY用于控制推送计算结果的最大延迟。</li><li>ROLLUP指定的聚合函数提供基于多层级的降采样聚合结果。</li><li>SMA提供基于数据块的自定义预计算功能。</li><li>TTL用来指定表的生命周期的参数。</li></ul> | 16 | CREATE TABLE | 调整 | 新增表参数语法<ul><li>COMMENT表注释。</li><li>WATERMARK指定窗口的关闭时间。</li><li>MAX_DELAY用于控制推送计算结果的最大延迟。</li><li>ROLLUP指定的聚合函数提供基于多层级的降采样聚合结果。</li><li>SMA提供基于数据块的自定义预计算功能。</li><li>TTL用来指定表的生命周期的参数。</li></ul>
| 17 | CREATE TOPIC | 新增 | 创建订阅主题。 | 17 | CREATE TOPIC | 新增 | 创建订阅主题。
| 18 | DROP ACCOUNT | 废除 | 2.x中为企业版功能3.0不再支持。语法暂时保留执行报“This statement is no longer supported”错误。 | 18 | DROP ACCOUNT | 废除 | 2.x 中为企业版功能3.0 不再支持。语法暂时保留,执行报 “This statement is no longer supported” 错误。
| 19 | DROP CONSUMER GROUP | 新增 | 删除消费组。 | 19 | DROP CONSUMER GROUP | 新增 | 删除消费组。
| 20 | DROP INDEX | 新增 | 删除索引。 | 20 | DROP INDEX | 新增 | 删除索引。
| 21 | DROP MNODE | 新增 | 创建管理节点。 | 21 | DROP MNODE | 新增 | 创建管理节点。
@ -54,52 +54,52 @@ description: "TDengine 3.0 版本的语法变更说明"
| 26 | EXPLAIN | 新增 | 查看查询语句的执行计划。 | 26 | EXPLAIN | 新增 | 查看查询语句的执行计划。
| 27 | GRANT | 新增 | 授予用户权限。 | 27 | GRANT | 新增 | 授予用户权限。
| 28 | KILL TRANSACTION | 新增 | 终止管理节点的事务。 | 28 | KILL TRANSACTION | 新增 | 终止管理节点的事务。
| 29 | KILL STREAM | 废除 | 终止连续查询。3.0版本不再支持连续查询,而是用更通用的流计算来代替。 | 29 | KILL STREAM | 废除 | 终止连续查询。3.0 版本不再支持连续查询,而是用更通用的流计算来代替。
| 31 | REVOKE | 新增 | 回收用户权限。 | 31 | REVOKE | 新增 | 回收用户权限。
| 32 | SELECT | 调整 | <ul><li>SELECT关闭隐式结果列输出列均需要由SELECT子句来指定。</li><li>DISTINCT功能全面支持。2.x版本只支持对标签列去重并且不可以和JOIN、GROUP BY等子句混用。</li><li>JOIN功能增强。增加支持JOIN后WHERE条件中有OR条件JOIN后的多表运算JOIN后的多表GROUP BY。</li><li>FROM后子查询功能大幅增强。不限制子查询嵌套层数支持子查询和UNION ALL混合使用移除其他一些之前版本的语法限制。</li><li>WHERE后可以使用任意的标量表达式。</li><li>GROUP BY功能增强。支持任意标量表达式及其组合的分组。</li><li>SESSION可以用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。</li><li>STATE_WINDOW可以用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。</li><li>ORDER BY功能大幅增强。不再必须和GROUP BY子句一起使用不再有排序表达式个数的限制增加支持NULLS FIRST/LAST语法功能支持符合语法语义的任意表达式。</li><li>新增PARTITION BY语法。替代原来的GROUP BY tags。</li></ul> | 32 | SELECT | 调整 | <ul><li>SELECT 关闭隐式结果列,输出列均需要由 SELECT 子句来指定。</li><li>DISTINCT 功能全面支持。2.x 版本只支持对标签列去重,并且不可以和 JOIN、GROUP BY 等子句混用。</li><li>JOIN 功能增强。增加支持JOIN WHERE 条件中有 OR 条件JOIN 后的多表运算JOIN 后的多表 GROUP BY。</li><li>FROM 后子查询功能大幅增强。不限制子查询嵌套层数;支持子查询和 UNION ALL 混合使用;移除其他一些之前版本的语法限制。</li><li>WHERE 后可以使用任意的标量表达式。</li><li>GROUP BY 功能增强。支持任意标量表达式及其组合的分组。</li><li>SESSION 可以用于超级表。之前版本,超级表的数据会被合并成一条时间线。</li><li>STATE_WINDOW 可以用于超级表。之前版本,超级表的数据会被合并成一条时间线。</li><li>ORDER BY 功能大幅增强。不再必须和 GROUP BY 子句一起使用;不再有排序表达式个数的限制;增加支持 NULLS FIRST/LAST 语法功能;支持符合语法语义的任意表达式。</li><li>新增 PARTITION BY 语法。替代原来的 GROUP BY tags。</li></ul>
| 33 | SHOW ACCOUNTS | 废除 | 2.x中为企业版功能3.0不再支持。语法暂时保留执行报“This statement is no longer supported”错误。 | 33 | SHOW ACCOUNTS | 废除 | 2.x 中为企业版功能3.0 不再支持。语法暂时保留,执行报 “This statement is no longer supported” 错误。
| 34 | SHOW APPS |新增 | 显示接入集群的应用(客户端)信息。 | 34 | SHOW APPS |新增 | 显示接入集群的应用(客户端)信息。
| 35 | SHOW CONSUMERS | 新增 | 显示当前数据库下所有活跃的消费者的信息。 | 35 | SHOW CONSUMERS | 新增 | 显示当前数据库下所有活跃的消费者的信息。
| 36 | SHOW DATABASES | 调整 | 3.0版本只显示数据库名。 | 36 | SHOW DATABASES | 调整 | 3.0 版本只显示数据库名。
| 37 | SHOW FUNCTIONS | 调整 | 3.0版本只显示自定义函数名。 | 37 | SHOW FUNCTIONS | 调整 | 3.0 版本只显示自定义函数名。
| 38 | SHOW LICENCE | 新增 | 和SHOW GRANTS 命令等效。 | 38 | SHOW LICENCE | 新增 | 和 SHOW GRANTS 命令等效。
| 39 | SHOW INDEXES | 新增 | 显示已创建的索引。 | 39 | SHOW INDEXES | 新增 | 显示已创建的索引。
| 40 | SHOW LOCAL VARIABLES | 新增 | 显示当前客户端配置参数的运行值。 | 40 | SHOW LOCAL VARIABLES | 新增 | 显示当前客户端配置参数的运行值。
| 41 | SHOW MODULES | 废除 | 显示当前系统中所安装的组件的信息。 | 41 | SHOW MODULES | 废除 | 显示当前系统中所安装的组件的信息。
| 42 | SHOW QNODES | 新增 | 显示当前系统中QNODE的信息。 | 42 | SHOW QNODES | 新增 | 显示当前系统中QNODE的信息。
| 43 | SHOW STABLES | 调整 | 3.0版本只显示超级表名。 | 43 | SHOW STABLES | 调整 | 3.0 版本只显示超级表名。
| 44 | SHOW STREAMS | 调整 | 2.x版本此命令显示系统中已创建的连续查询的信息。3.0版本废除了连续查询,用流代替。此命令显示已创建的流。 | 44 | SHOW STREAMS | 调整 | 2.x 版本此命令显示系统中已创建的连续查询的信息。3.0 版本废除了连续查询,用流代替。此命令显示已创建的流。
| 45 | SHOW SUBSCRIPTIONS | 新增 | 显示当前数据库下的所有的订阅关系 | 45 | SHOW SUBSCRIPTIONS | 新增 | 显示当前数据库下的所有的订阅关系
| 46 | SHOW TABLES | 调整 | 3.0版本只显示表名。 | 46 | SHOW TABLES | 调整 | 3.0 版本只显示表名。
| 47 | SHOW TABLE DISTRIBUTED | 新增 | 显示表的数据分布信息。代替2.x版本中的SELECT _block_dist() FROM \{ tb_name | stb_name }方式。 | 47 | SHOW TABLE DISTRIBUTED | 新增 | 显示表的数据分布信息。代替 2.x 版本中的 `SELECT _block_dist() FROM tb_name` 方式。
| 48 | SHOW TOPICS | 新增 | 显示当前数据库下的所有订阅主题。 | 48 | SHOW TOPICS | 新增 | 显示当前数据库下的所有订阅主题。
| 49 | SHOW TRANSACTIONS | 新增 | 显示当前系统中正在执行的事务的信息。 | 49 | SHOW TRANSACTIONS | 新增 | 显示当前系统中正在执行的事务的信息。
| 50 | SHOW DNODE VARIABLES | 新增 |显示指定DNODE的配置参数。 | 50 | SHOW DNODE VARIABLES | 新增 |显示指定 DNODE 的配置参数。
| 51 | SHOW VNODES | 暂不支持 | 显示当前系统中VNODE的信息。3.0.0版本暂不支持。 | 51 | SHOW VNODES | 暂不支持 | 显示当前系统中 VNODE 的信息。
| 52 | TRIM DATABASE | 新增 | 删除过期数据,并根据多级存储的配置归整数据。 | 52 | TRIM DATABASE | 新增 | 删除过期数据,并根据多级存储的配置归整数据。
| 53 | REDISTRIBUTE VGROUP | 新增 | 调整VGROUP中VNODE的分布。 | 53 | REDISTRIBUTE VGROUP | 新增 | 调整 VGROUP VNODE 的分布。
| 54 | BALANCE VGROUP | 新增 | 自动调整VGROUP中VNODE的分布。 | 54 | BALANCE VGROUP | 新增 | 自动调整 VGROUP中 VNODE 的分布。
## SQL 函数变更 ## SQL 函数变更
| # | **函数** | ** <div style={{width: 60}}>差异性</div> ** | **说明** | | # | **函数** | ** <div style={{width: 60}}>差异性</div> ** | **说明** |
| - | :------- | :-------- | :------- | | - | :------- | :-------- | :------- |
| 1 | TWA | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 1 | TWA | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 2 | IRATE | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 2 | IRATE | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 3 | LEASTSQUARES | 增强 | 可以用于超级表 | 3 | LEASTSQUARES | 增强 | 可以用于超级表。
| 4 | ELAPSED | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 4 | ELAPSED | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 5 | DIFF | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 5 | DIFF | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 6 | DERIVATIVE | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 6 | DERIVATIVE | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 7 | CSUM | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 7 | CSUM | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 8 | MAVG | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 8 | MAVG | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 9 | SAMPLE | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 9 | SAMPLE | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 10 | STATECOUNT | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 10 | STATECOUNT | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 11 | STATEDURATION | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 11 | STATEDURATION | 增强 | 可以直接用于超级表。之前版本,超级表的数据会被合并成一条时间线。
| 12 | TIMETRUNCATE | 增强 | 增加ignore_timezone参数可选是否使用默认值为1. | 12 | TIMETRUNCATE | 增强 | 增加 ignore_timezone 参数,可选是否使用,默认值为 1。
## SCHEMALESS 变更 ## SCHEMALESS 变更
| # | **元素** | **<div style={{width: 60}}>差异性</div>** | **说明** | | # | **元素** | **<div style={{width: 60}}>差异性</div>** | **说明** |
| - | :------- | :-------- | :------- | | - | :------- | :-------- | :------- |
| 1 | 主键ts 变更为 _ts | 变更 | schemaless自动建的列名用 _ 开头不同于2.x。 | 1 | 主键 ts 变更为 _ts | 变更 | schemaless 自动建的列名用 `_` 开头不同于2.x。

View File

@ -14,9 +14,9 @@ description: 关联查询详细描述
连接条件是指进行表关联所指定的条件TDengine 支持的所有关联查询都需要指定连接条件连接条件通常Inner Join 和 Window Join 例外)只出现在 `ON` 之后。根据语义Inner Join 中出现在 `WHERE` 之后的条件也可以视作连接条件,而 Window Join 是通过 `WINDOW_OFFSET` 来指定连接条件。 连接条件是指进行表关联所指定的条件TDengine 支持的所有关联查询都需要指定连接条件连接条件通常Inner Join 和 Window Join 例外)只出现在 `ON` 之后。根据语义Inner Join 中出现在 `WHERE` 之后的条件也可以视作连接条件,而 Window Join 是通过 `WINDOW_OFFSET` 来指定连接条件。
除 ASOF Join 外TDengine 支持的所有 Join 类型都必须显式指定连接条件ASOF Join 因为默认定义有隐式的连接条件,所以(在默认条件可以满足需求的情况下)可以不必显式指定连接条件。 除 ASOF Join 外TDengine 支持的所有 Join 类型都必须显式指定连接条件ASOF Join 因为默认定义有隐式的连接条件,所以(在默认条件可以满足需求的情况下)可以不必显式指定连接条件。
除 ASOF/Window Join 外,连接条件中除了包含主连接条件外,还可以包含任意多条其他连接条件,主连接条件与其他连接条件间必须是 `AND` 关系而其他连接条件之间则没有这个限制。其他连接条件中可以包含主键列、Tag 、普通列、常量及其标量函数或运算的任意逻辑运算组合。 除 ASOF/Window Join 外,连接条件中除了包含主连接条件外,还可以包含任意多条其他连接条件,主连接条件与其他连接条件间必须是 `AND` 关系而其他连接条件之间则没有这个限制。其他连接条件中可以包含主键列、Tag、普通列、常量及其标量函数或运算的任意逻辑运算组合。
以智能电表为例,下面这几条 SQL 都包含合法的连接条件: 以智能电表为例,下面这几条 SQL 都包含合法的连接条件:
@ -196,7 +196,7 @@ SELECT ... FROM table_name1 LEFT|RIGHT ASOF JOIN table_name2 [ON ...] [JLIMIT jl
- 如果不含 `ON` 子句或 `ON` 子句中未指定主键列的匹配规则,则默认主键匹配规则运算符是 “>=”, 即(对 Left ASOF Join 来说)右表中主键时戳小于等于左表主键时戳的行数据。不支持多个主连接条件。 - 如果不含 `ON` 子句或 `ON` 子句中未指定主键列的匹配规则,则默认主键匹配规则运算符是 “>=”, 即(对 Left ASOF Join 来说)右表中主键时戳小于等于左表主键时戳的行数据。不支持多个主连接条件。
- `ON` 子句中还可以指定除主键列外的 Tag、普通列不支持标量函数及运算之间的等值条件用于分组计算除此之外不支持其他类型的条件。 - `ON` 子句中还可以指定除主键列外的 Tag、普通列不支持标量函数及运算之间的等值条件用于分组计算除此之外不支持其他类型的条件。
- 所有 ON 条件间只支持 `AND` 运算。 - 所有 ON 条件间只支持 `AND` 运算。
- `JLIMIT` 用于指定单行匹配结果的最大行数可选未指定时默认值为1即左/右表每行数据最多从右/左表中获得一行匹配结果。`JLIMIT` 取值范围为 [0, 1024]。符合匹配条件的 `jlimit_num` 条数据不要求时间戳相同,当右/左表中不存在满足条件的 `jlimit_num` 条数据时,返回的结果行数可能小于 `jlimit_num`;当右/左表中存在符合条件的多于 `jlimit_num` 条数据时,如果时间戳相同将随机返回 `jlimit_num` 条数据。 - `JLIMIT` 用于指定单行匹配结果的最大行数,可选,未指定时默认值为 1即左/右表每行数据最多从右/左表中获得一行匹配结果。`JLIMIT` 取值范围为 [0, 1024]。符合匹配条件的 `jlimit_num` 条数据不要求时间戳相同,当右/左表中不存在满足条件的 `jlimit_num` 条数据时,返回的结果行数可能小于 `jlimit_num`;当右/左表中存在符合条件的多于 `jlimit_num` 条数据时,如果时间戳相同将随机返回 `jlimit_num` 条数据。
#### 示例 #### 示例

View File

@ -4,7 +4,7 @@ sidebar_label: 可配置压缩
description: 可配置压缩算法 description: 可配置压缩算法
--- ---
TDengine 3.3.0.0 版本开始TDengine 提供了更高级的压缩功能,用户可以在建表时针对每一列配置是否进行压缩、以及使用的压缩算法和压缩级别。 v3.3.0.0 开始TDengine 提供了更高级的压缩功能,用户可以在建表时针对每一列配置是否进行压缩、以及使用的压缩算法和压缩级别。
## 压缩术语定义 ## 压缩术语定义
@ -15,7 +15,7 @@ description: 可配置压缩算法
### 压缩级别 ### 压缩级别
在本文中特指二级压缩算法内部的级别比如zstd至少8个level可选每个level 下都有不同表现,本质是压缩率、压缩速度、解压速度之间的 tradeoff为了避免选择困难特简化定义为如下三种级别 在本文中特指二级压缩算法内部的级别,比如 zstd至少 8 level 可选,每个 level 下都有不同表现,本质是压缩率、压缩速度、解压速度之间的 tradeoff为了避免选择困难特简化定义为如下三种级别
- high压缩率最高压缩速度和解压速度相对最差。 - high压缩率最高压缩速度和解压速度相对最差。
- low压缩速度和解压速度最好压缩率相对最低。 - low压缩速度和解压速度最好压缩率相对最低。
@ -23,9 +23,9 @@ description: 可配置压缩算法
### 压缩算法列表 ### 压缩算法列表
- 编码算法列表(一级压缩):simple8b, bit-packing,delta-i, delta-d, disabled - 编码算法列表(一级压缩simple8b、bit-packing、delta-i、delta-d、disabled
- 压缩算法列表(二级压缩): lz4、zlib、zstd、tsz、xz、disabled - 压缩算法列表(二级压缩):lz4、zlib、zstd、tsz、xz、disabled
- 各个数据类型的默认压缩算法列表和适用范围 - 各个数据类型的默认压缩算法列表和适用范围
@ -50,9 +50,9 @@ CREATE [dbname.]tabname (colName colType [ENCODE 'encode_type'] [COMPRESS 'compr
**参数说明** **参数说明**
- tabname超级表或者普通表名称 - tabname超级表或者普通表名称
- encode_type: 一级压缩,具体参数见上面列表 - encode_type一级压缩,具体参数见上面列表
- compress_type: 二级压缩,具体参数见上面列表 - compress_type:二级压缩,具体参数见上面列表
- level: 特指二级压缩的级别默认值为medium, 支持简写为 'h'/'l'/'m' - level:特指二级压缩的级别,默认值为 medium支持简写为 'h'、'l'、'm'
**功能说明** **功能说明**
@ -67,8 +67,8 @@ ALTER TABLE [db_name.]tabName MODIFY COLUMN colName [ENCODE 'ecode_type'] [COMPR
**参数说明** **参数说明**
- tabName: 表名,可以为超级表、普通表 - tabName表名,可以为超级表、普通表
- colName: 待更改压缩算法的列, 只能为普通列 - colName:待更改压缩算法的列,只能为普通列
**功能说明** **功能说明**
@ -87,4 +87,4 @@ DESCRIBE [dbname.]tabName
## 兼容性 ## 兼容性
- 完全兼容已经存在的数据 - 完全兼容已经存在的数据
- 从更低版本升级到 3.3.0.0 后不能回退 - 从更低版本升级到 v3.3.0.0 后不能回退

View File

@ -4,14 +4,13 @@ title: "视图"
sidebar_label: "视图" sidebar_label: "视图"
--- ---
TDengine 3.2.1.0 开始TDengine 企业版提供视图功能,便于用户简化操作,提升用户间的分享能力。 v3.2.1.0 开始TDengine 企业版提供视图功能,便于用户简化操作,提升用户间的分享能力。
视图View本质上是一个存储在数据库中的查询语句。视图非物化视图本身不包含数据只有在从视图读取数据时才动态执行视图所指定的查询语句。我们在创建视图时指定一个名称然后可以像使用普通表一样对其进行查询等操作。视图的使用需遵循以下规则 视图View本质上是一个存储在数据库中的查询语句。视图非物化视图本身不包含数据只有在从视图读取数据时才动态执行视图所指定的查询语句。我们在创建视图时指定一个名称然后可以像使用普通表一样对其进行查询等操作。视图的使用需遵循以下规则
- 视图可以嵌套定义和使用,视图与创建时指定的或当前数据库绑定使用。 - 视图可以嵌套定义和使用,视图与创建时指定的或当前数据库绑定使用。
- 在同一个数据库内,视图名称不允许重名,视图名跟表名也推荐不重名(不强制)。当出现视图与表名重名时,写入、查询、授权、回收权限等操作优先使用同名表。 - 在同一个数据库内,视图名称不允许重名,视图名跟表名也推荐不重名(不强制)。当出现视图与表名重名时,写入、查询、授权、回收权限等操作优先使用同名表。
## 语法 ## 语法
### 创建(更新)视图 ### 创建(更新)视图
@ -58,7 +57,7 @@ DROP VIEW [IF EXISTS] [db_name.]view_name;
### 规则 ### 规则
- 视图的创建者和 root 用户默认具备所有权限。 - 视图的创建者和 root 用户默认具备所有权限。
- 对其他用户进行授权与回收权限可以通过 GRANT 和 REVOKE 语句进行,该操作只能由 root 用户进行。 - 对其他用户进行授权与回收权限可以通过 GRANT 和 REVOKE 语句进行,该操作只能由 root 用户进行。
- 视图权限需单独授权与回收通过db.*进行的授权与回收不含视图权限。 - 视图权限需单独授权与回收,通过 db.* 进行的授权与回收不含视图权限。
- 视图可以嵌套定义与使用,同理对视图权限的校验也是递归进行的。 - 视图可以嵌套定义与使用,同理对视图权限的校验也是递归进行的。
- 为了方便视图的分享与使用,引入视图有效用户(即视图的创建用户)的概念,被授权用户可以使用视图有效用户的库、表及嵌套视图的读写权限。注:视图被 REPLACE 后有效用户也会被更新。 - 为了方便视图的分享与使用,引入视图有效用户(即视图的创建用户)的概念,被授权用户可以使用视图有效用户的库、表及嵌套视图的读写权限。注:视图被 REPLACE 后有效用户也会被更新。
@ -67,7 +66,7 @@ DROP VIEW [IF EXISTS] [db_name.]view_name;
| 序号 | 操作 | 权限要求 | | 序号 | 操作 | 权限要求 |
| ---- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | ---- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | CREATE VIEW <br/>(创建新用户) | 用户对视图所属数据库有 WRITE 权限<br/><br/> 用户对视图的目标库、表、视图有查询权限若查询中的对象是视图需满足当前表中第8条规则 | | 1 | CREATE VIEW <br/>(创建新用户) | 用户对视图所属数据库有 WRITE 权限<br/><br/> 用户对视图的目标库、表、视图有查询权限若查询中的对象是视图需满足当前表中第8条规则 |
| 2 | CREATE OR REPLACE VIEW <br/>(覆盖旧视图) | 用户对视图所属数据库有 WRITE 权限 且 对旧有视图有 ALTER 权限 <br/><br/> 用户对视图的目标库、表、视图有查询权限若查询中的对象是视图需满足当前表中第8条规则 | | 2 | CREATE OR REPLACE VIEW <br/>(覆盖旧视图) | 用户对视图所属数据库有 WRITE 权限 且 对旧有视图有 ALTER 权限 <br/><br/> 用户对视图的目标库、表、视图有查询权限,若查询中的对象是视图需满足当前表中第 8 条规则 |
| 3 | DROP VIEW | 用户对视图有 ALTER 权限 | | 3 | DROP VIEW | 用户对视图有 ALTER 权限 |
| 4 | SHOW VIEWS | 无 | | 4 | SHOW VIEWS | 无 |
| 5 | SHOW CREATE VIEW | 无 | | 5 | SHOW CREATE VIEW | 无 |

View File

@ -557,8 +557,10 @@ description: TDengine 服务端的错误码列表和详细说明
| 错误码 | 错误描述 | 可能的出错场景或者可能的原因 | 建议用户采取的措施 | | 错误码 | 错误描述 | 可能的出错场景或者可能的原因 | 建议用户采取的措施 |
| ---------- | --------------------- | -------------------------------------------------------------------------------- | ------------------------------ | | ---------- | --------------------- | -------------------------------------------------------------------------------- | ------------------------------ |
| 0x800003E6 | Consumer not exist | Consumer 超时下线 | 重新建consumer订阅数据 |
| 0x800003EA | Consumer not ready | Consumer 正在平衡中 | 等待2秒后重试 |
| 0x80004000 | Invalid message | 订阅到的数据非法,一般不会出现 | 具体查看client端的错误日志提示 | | 0x80004000 | Invalid message | 订阅到的数据非法,一般不会出现 | 具体查看client端的错误日志提示 |
| 0x80004001 | Consumer mismatch | 订阅请求的vnode和重新分配的vnode不一致一般存在于有新消费者加入相同消费者组里时 | 内部错误,不暴露给用户 | | 0x80004001 | Consumer mismatch | 订阅请求的vnode和重新分配的vnode不一致一般存在于有新消费者加入相同消费者组里时 | 内部错误 |
| 0x80004002 | Consumer closed | 消费者已经不存在了 | 查看是否已经close掉了 | | 0x80004002 | Consumer closed | 消费者已经不存在了 | 查看是否已经close掉了 |
| 0x80004017 | Invalid status, please subscribe topic first | 数据订阅状态不对 | 没有调用 subscribe直接 poll 数据 | | 0x80004017 | Invalid status, please subscribe topic first | 数据订阅状态不对 | 没有调用 subscribe直接 poll 数据 |
| 0x80004100 | Stream task not exist | 流计算任务不存在 | 具体查看server端的错误日志 | | 0x80004100 | Stream task not exist | 流计算任务不存在 | 具体查看server端的错误日志 |

View File

@ -28,7 +28,6 @@
#define tqInfoC(...) do { if (cDebugFlag & DEBUG_INFO || tqClientDebugFlag & DEBUG_INFO) { taosPrintLog("TQ INFO ", DEBUG_INFO, tqClientDebugFlag|cDebugFlag, __VA_ARGS__); }} while(0) #define tqInfoC(...) do { if (cDebugFlag & DEBUG_INFO || tqClientDebugFlag & DEBUG_INFO) { taosPrintLog("TQ INFO ", DEBUG_INFO, tqClientDebugFlag|cDebugFlag, __VA_ARGS__); }} while(0)
#define tqDebugC(...) do { if (cDebugFlag & DEBUG_DEBUG || tqClientDebugFlag & DEBUG_DEBUG) { taosPrintLog("TQ DEBUG ", DEBUG_DEBUG, tqClientDebugFlag|cDebugFlag, __VA_ARGS__); }} while(0) #define tqDebugC(...) do { if (cDebugFlag & DEBUG_DEBUG || tqClientDebugFlag & DEBUG_DEBUG) { taosPrintLog("TQ DEBUG ", DEBUG_DEBUG, tqClientDebugFlag|cDebugFlag, __VA_ARGS__); }} while(0)
#define EMPTY_BLOCK_POLL_IDLE_DURATION 10
#define DEFAULT_AUTO_COMMIT_INTERVAL 5000 #define DEFAULT_AUTO_COMMIT_INTERVAL 5000
#define DEFAULT_HEARTBEAT_INTERVAL 3000 #define DEFAULT_HEARTBEAT_INTERVAL 3000
#define DEFAULT_ASKEP_INTERVAL 1000 #define DEFAULT_ASKEP_INTERVAL 1000
@ -149,7 +148,6 @@ struct tmq_t {
STscObj* pTscObj; // connection STscObj* pTscObj; // connection
SArray* clientTopics; // SArray<SMqClientTopic> SArray* clientTopics; // SArray<SMqClientTopic>
STaosQueue* mqueue; // queue of rsp STaosQueue* mqueue; // queue of rsp
STaosQall* qall;
STaosQueue* delayedTask; // delayed task queue for heartbeat and auto commit STaosQueue* delayedTask; // delayed task queue for heartbeat and auto commit
tsem2_t rspSem; tsem2_t rspSem;
}; };
@ -174,7 +172,6 @@ typedef struct {
int32_t vgId; int32_t vgId;
int32_t vgStatus; int32_t vgStatus;
int32_t vgSkipCnt; // here used to mark the slow vgroups int32_t vgSkipCnt; // here used to mark the slow vgroups
int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
int64_t blockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data int64_t blockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
int64_t blockSleepForReplay; // once empty block is received, idle for ignoreCnt then start to poll data int64_t blockSleepForReplay; // once empty block is received, idle for ignoreCnt then start to poll data
bool seekUpdated; // offset is updated by seek operator, therefore, not update by vnode rsp. bool seekUpdated; // offset is updated by seek operator, therefore, not update by vnode rsp.
@ -1134,7 +1131,7 @@ void tmqSendHbReq(void* param, void* tmrId) {
tDestroySMqHbReq(&req); tDestroySMqHbReq(&req);
if (tmrId != NULL) { if (tmrId != NULL) {
bool ret = taosTmrReset(tmqSendHbReq, tmq->heartBeatIntervalMs, param, tmqMgmt.timer, &tmq->hbLiveTimer); bool ret = taosTmrReset(tmqSendHbReq, tmq->heartBeatIntervalMs, param, tmqMgmt.timer, &tmq->hbLiveTimer);
tqDebugC("consumer:0x%" PRIx64 " reset timer for tmq heartbeat:%d, pollFlag:%d", tmq->consumerId, ret, tmq->pollFlag); tqDebugC("consumer:0x%" PRIx64 " reset timer for tmq heartbeat ret:%d, interval:%d, pollFlag:%d", tmq->consumerId, ret, tmq->heartBeatIntervalMs, tmq->pollFlag);
} }
int32_t ret = taosReleaseRef(tmqMgmt.rsetId, refId); int32_t ret = taosReleaseRef(tmqMgmt.rsetId, refId);
if (ret != 0){ if (ret != 0){
@ -1226,7 +1223,6 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
.epSet = pVgEp->epSet, .epSet = pVgEp->epSet,
.vgStatus = pInfo ? pInfo->vgStatus : TMQ_VG_STATUS__IDLE, .vgStatus = pInfo ? pInfo->vgStatus : TMQ_VG_STATUS__IDLE,
.vgSkipCnt = 0, .vgSkipCnt = 0,
.emptyBlockReceiveTs = 0,
.blockReceiveTs = 0, .blockReceiveTs = 0,
.blockSleepForReplay = 0, .blockSleepForReplay = 0,
.numOfRows = pInfo ? pInfo->numOfRows : 0, .numOfRows = pInfo ? pInfo->numOfRows : 0,
@ -1487,27 +1483,14 @@ END:
} }
static int32_t tmqHandleAllDelayedTask(tmq_t* pTmq) { static int32_t tmqHandleAllDelayedTask(tmq_t* pTmq) {
STaosQall* qall = NULL; tqDebugC("consumer:0x%" PRIx64 " handle delayed %d tasks before poll data", pTmq->consumerId, taosQueueItemSize(pTmq->delayedTask));
int32_t code = 0; while (1) {
int8_t* pTaskType = NULL;
code = taosAllocateQall(&qall); taosReadQitem(pTmq->delayedTask, (void**)&pTaskType);
if (code) { if (pTaskType == NULL) {break;}
tqErrorC("consumer:0x%" PRIx64 ", failed to allocate qall, code:%s", pTmq->consumerId, tstrerror(code));
return code;
}
int32_t numOfItems = taosReadAllQitems(pTmq->delayedTask, qall);
if (numOfItems == 0) {
taosFreeQall(qall);
return 0;
}
tqDebugC("consumer:0x%" PRIx64 " handle delayed %d tasks before poll data", pTmq->consumerId, numOfItems);
int8_t* pTaskType = NULL;
while (taosGetQitem(qall, (void**)&pTaskType) != 0) {
if (*pTaskType == TMQ_DELAYED_TASK__ASK_EP) { if (*pTaskType == TMQ_DELAYED_TASK__ASK_EP) {
tqDebugC("consumer:0x%" PRIx64 " retrieve ask ep timer", pTmq->consumerId); tqDebugC("consumer:0x%" PRIx64 " retrieve ask ep timer", pTmq->consumerId);
code = askEp(pTmq, NULL, false, false); int32_t code = askEp(pTmq, NULL, false, false);
if (code != 0) { if (code != 0) {
tqErrorC("consumer:0x%" PRIx64 " failed to ask ep, code:%s", pTmq->consumerId, tstrerror(code)); tqErrorC("consumer:0x%" PRIx64 " failed to ask ep, code:%s", pTmq->consumerId, tstrerror(code));
} }
@ -1530,23 +1513,15 @@ static int32_t tmqHandleAllDelayedTask(tmq_t* pTmq) {
taosFreeQitem(pTaskType); taosFreeQitem(pTaskType);
} }
taosFreeQall(qall);
return 0; return 0;
} }
void tmqClearUnhandleMsg(tmq_t* tmq) { void tmqClearUnhandleMsg(tmq_t* tmq) {
if (tmq == NULL) return; if (tmq == NULL) return;
SMqRspWrapper* rspWrapper = NULL; while (1) {
while (taosGetQitem(tmq->qall, (void**)&rspWrapper) != 0) { SMqRspWrapper* rspWrapper = NULL;
tmqFreeRspWrapper(rspWrapper); taosReadQitem(tmq->mqueue, (void**)&rspWrapper);
taosFreeQitem(rspWrapper); if (rspWrapper == NULL) break;
}
rspWrapper = NULL;
if (taosReadAllQitems(tmq->mqueue, tmq->qall) == 0){
return;
}
while (taosGetQitem(tmq->qall, (void**)&rspWrapper) != 0) {
tmqFreeRspWrapper(rspWrapper); tmqFreeRspWrapper(rspWrapper);
taosFreeQitem(rspWrapper); taosFreeQitem(rspWrapper);
} }
@ -1613,7 +1588,6 @@ void tmqFreeImpl(void* handle) {
taosCloseQueue(tmq->delayedTask); taosCloseQueue(tmq->delayedTask);
} }
taosFreeQall(tmq->qall);
if(tsem2_destroy(&tmq->rspSem) != 0) { if(tsem2_destroy(&tmq->rspSem) != 0) {
tqErrorC("failed to destroy sem in free tmq"); tqErrorC("failed to destroy sem in free tmq");
} }
@ -1739,14 +1713,6 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
goto _failed; goto _failed;
} }
code = taosAllocateQall(&pTmq->qall);
if (code) {
tqErrorC("consumer:0x%" PRIx64 " setup failed since %s, groupId:%s", pTmq->consumerId, tstrerror(code),
pTmq->groupId);
SET_ERROR_MSG_TMQ("allocate qall failed")
goto _failed;
}
if (conf->groupId[0] == 0) { if (conf->groupId[0] == 0) {
tqErrorC("consumer:0x%" PRIx64 " setup failed since %s, groupId:%s", pTmq->consumerId, tstrerror(code), tqErrorC("consumer:0x%" PRIx64 " setup failed since %s, groupId:%s", pTmq->consumerId, tstrerror(code),
pTmq->groupId); pTmq->groupId);
@ -2128,7 +2094,6 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
} }
} }
if (tsem2_post(&tmq->rspSem) != 0){ if (tsem2_post(&tmq->rspSem) != 0){
tqErrorC("failed to post rsp sem, consumer:0x%" PRIx64, tmq->consumerId); tqErrorC("failed to post rsp sem, consumer:0x%" PRIx64, tmq->consumerId);
} }
@ -2322,7 +2287,7 @@ static int32_t tmqPollImpl(tmq_t* tmq) {
taosWLockLatch(&tmq->lock); taosWLockLatch(&tmq->lock);
if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__LOST){ if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__LOST){
code = TSDB_CODE_TMQ_CONSUMER_MISMATCH; code = TSDB_CODE_MND_CONSUMER_NOT_EXIST;
goto end; goto end;
} }
@ -2344,14 +2309,7 @@ static int32_t tmqPollImpl(tmq_t* tmq) {
if (pVg == NULL) { if (pVg == NULL) {
continue; continue;
} }
int64_t elapsed = taosGetTimestampMs() - pVg->emptyBlockReceiveTs; int64_t elapsed = taosGetTimestampMs() - pVg->blockReceiveTs;
if (elapsed < EMPTY_BLOCK_POLL_IDLE_DURATION && elapsed >= 0) { // less than 10ms
tqDebugC("consumer:0x%" PRIx64 " epoch %d, vgId:%d idle for 10ms before start next poll", tmq->consumerId,
tmq->epoch, pVg->vgId);
continue;
}
elapsed = taosGetTimestampMs() - pVg->blockReceiveTs;
if (tmq->replayEnable && elapsed < pVg->blockSleepForReplay && elapsed >= 0) { if (tmq->replayEnable && elapsed < pVg->blockSleepForReplay && elapsed >= 0) {
tqDebugC("consumer:0x%" PRIx64 " epoch %d, vgId:%d idle for %" PRId64 "ms before start next poll when replay", tqDebugC("consumer:0x%" PRIx64 " epoch %d, vgId:%d idle for %" PRId64 "ms before start next poll when replay",
tmq->consumerId, tmq->epoch, pVg->vgId, pVg->blockSleepForReplay); tmq->consumerId, tmq->epoch, pVg->vgId, pVg->blockSleepForReplay);
@ -2430,12 +2388,12 @@ static int32_t processMqRspError(tmq_t* tmq, SMqRspWrapper* pRspWrapper){
if (pRspWrapper->code == TSDB_CODE_VND_INVALID_VGROUP_ID) { // for vnode transform if (pRspWrapper->code == TSDB_CODE_VND_INVALID_VGROUP_ID) { // for vnode transform
code = askEp(tmq, NULL, false, true); code = askEp(tmq, NULL, false, true);
if (code != 0) { if (code != 0) {
tqErrorC("consumer:0x%" PRIx64 " failed to ask ep, code:%s", tmq->consumerId, tstrerror(code)); tqErrorC("consumer:0x%" PRIx64 " failed to ask ep wher vnode transform, code:%s", tmq->consumerId, tstrerror(code));
} }
} else if (pRspWrapper->code == TSDB_CODE_TMQ_CONSUMER_MISMATCH) { } else if (pRspWrapper->code == TSDB_CODE_TMQ_CONSUMER_MISMATCH) {
code = askEp(tmq, NULL, false, false); code = syncAskEp(tmq);
if (code != 0) { if (code != 0) {
tqErrorC("consumer:0x%" PRIx64 " failed to ask ep, code:%s", tmq->consumerId, tstrerror(code)); tqErrorC("consumer:0x%" PRIx64 " failed to ask ep when consumer mismatch, code:%s", tmq->consumerId, tstrerror(code));
} }
} else if (pRspWrapper->code == TSDB_CODE_TMQ_NO_TABLE_QUALIFIED){ } else if (pRspWrapper->code == TSDB_CODE_TMQ_NO_TABLE_QUALIFIED){
code = 0; code = 0;
@ -2446,7 +2404,6 @@ static int32_t processMqRspError(tmq_t* tmq, SMqRspWrapper* pRspWrapper){
SMqClientVg* pVg = NULL; SMqClientVg* pVg = NULL;
getVgInfo(tmq, pollRspWrapper->topicName, pollRspWrapper->vgId, &pVg); getVgInfo(tmq, pollRspWrapper->topicName, pollRspWrapper->vgId, &pVg);
if (pVg) { if (pVg) {
pVg->emptyBlockReceiveTs = taosGetTimestampMs();
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
} }
taosWUnLockLatch(&tmq->lock); taosWUnLockLatch(&tmq->lock);
@ -2525,7 +2482,6 @@ static SMqRspObj* processMqRsp(tmq_t* tmq, SMqRspWrapper* pRspWrapper){
tqDebugC("consumer:0x%" PRIx64 " empty block received, vgId:%d, offset:%s, vg total:%" PRId64 tqDebugC("consumer:0x%" PRIx64 " empty block received, vgId:%d, offset:%s, vg total:%" PRId64
", total:%" PRId64 ", QID:0x%" PRIx64, ", total:%" PRId64 ", QID:0x%" PRIx64,
tmq->consumerId, pVg->vgId, buf, pVg->numOfRows, tmq->totalRows, pollRspWrapper->reqId); tmq->consumerId, pVg->vgId, buf, pVg->numOfRows, tmq->totalRows, pollRspWrapper->reqId);
pVg->emptyBlockReceiveTs = taosGetTimestampMs();
} else { } else {
pRspObj = buildRsp(pollRspWrapper); pRspObj = buildRsp(pollRspWrapper);
if (pRspObj == NULL) { if (pRspObj == NULL) {
@ -2539,7 +2495,6 @@ static SMqRspObj* processMqRsp(tmq_t* tmq, SMqRspWrapper* pRspWrapper){
tmqBuildRspFromWrapperInner(pollRspWrapper, pVg, &numOfRows, pRspObj); tmqBuildRspFromWrapperInner(pollRspWrapper, pVg, &numOfRows, pRspObj);
tmq->totalRows += numOfRows; tmq->totalRows += numOfRows;
} }
pVg->emptyBlockReceiveTs = 0;
if (tmq->replayEnable && pRspWrapper->tmqRspType != TMQ_MSG_TYPE__POLL_RAW_DATA_RSP) { if (tmq->replayEnable && pRspWrapper->tmqRspType != TMQ_MSG_TYPE__POLL_RAW_DATA_RSP) {
pVg->blockReceiveTs = taosGetTimestampMs(); pVg->blockReceiveTs = taosGetTimestampMs();
pVg->blockSleepForReplay = pRspObj->dataRsp.sleepTime; pVg->blockSleepForReplay = pRspObj->dataRsp.sleepTime;
@ -2575,22 +2530,14 @@ END:
} }
static void* tmqHandleAllRsp(tmq_t* tmq) { static void* tmqHandleAllRsp(tmq_t* tmq) {
tqDebugC("consumer:0x%" PRIx64 " start to handle the rsp, total:%d", tmq->consumerId, taosQallItemSize(tmq->qall)); tqDebugC("consumer:0x%" PRIx64 " start to handle the rsp, total:%d", tmq->consumerId, taosQueueItemSize(tmq->mqueue));
int32_t code = 0; int32_t code = 0;
void* returnVal = NULL; void* returnVal = NULL;
while (1) { while (1) {
SMqRspWrapper* pRspWrapper = NULL; SMqRspWrapper* pRspWrapper = NULL;
if (taosGetQitem(tmq->qall, (void**)&pRspWrapper) == 0) { taosReadQitem(tmq->mqueue, (void**)&pRspWrapper);
code = taosReadAllQitems(tmq->mqueue, tmq->qall); if (pRspWrapper == NULL) {break;}
if (code == 0){
goto END;
}
code = taosGetQitem(tmq->qall, (void**)&pRspWrapper);
if (code == 0) {
goto END;
}
}
tqDebugC("consumer:0x%" PRIx64 " handle rsp, type:%s", tmq->consumerId, tmqMsgTypeStr[pRspWrapper->tmqRspType]); tqDebugC("consumer:0x%" PRIx64 " handle rsp, type:%s", tmq->consumerId, tmqMsgTypeStr[pRspWrapper->tmqRspType]);
if (pRspWrapper->code != 0) { if (pRspWrapper->code != 0) {
@ -2629,9 +2576,6 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
code = tmqHandleAllDelayedTask(tmq); code = tmqHandleAllDelayedTask(tmq);
TSDB_CHECK_CODE(code, lino, END); TSDB_CHECK_CODE(code, lino, END);
code = tmqPollImpl(tmq);
TSDB_CHECK_CODE(code, lino, END);
rspObj = tmqHandleAllRsp(tmq); rspObj = tmqHandleAllRsp(tmq);
if (rspObj) { if (rspObj) {
tqDebugC("consumer:0x%" PRIx64 " return rsp %p", tmq->consumerId, rspObj); tqDebugC("consumer:0x%" PRIx64 " return rsp %p", tmq->consumerId, rspObj);
@ -2640,11 +2584,14 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
code = terrno; code = terrno;
TSDB_CHECK_CODE(code, lino, END); TSDB_CHECK_CODE(code, lino, END);
code = tmqPollImpl(tmq);
TSDB_CHECK_CODE(code, lino, END);
if (timeout >= 0) { if (timeout >= 0) {
int64_t currentTime = taosGetTimestampMs(); int64_t currentTime = taosGetTimestampMs();
int64_t elapsedTime = currentTime - startTime; int64_t elapsedTime = currentTime - startTime;
TSDB_CHECK_CONDITION(elapsedTime <= timeout && elapsedTime >= 0, code, lino, END, 0);
(void)tsem2_timewait(&tmq->rspSem, (timeout - elapsedTime)); (void)tsem2_timewait(&tmq->rspSem, (timeout - elapsedTime));
TSDB_CHECK_CONDITION(elapsedTime < timeout && elapsedTime >= 0, code, lino, END, 0);
} else { } else {
(void)tsem2_timewait(&tmq->rspSem, 1000); (void)tsem2_timewait(&tmq->rspSem, 1000);
} }

View File

@ -37,6 +37,10 @@ class TDTestCase:
tdLog.info(cmdStr) tdLog.info(cmdStr)
os.system(cmdStr) os.system(cmdStr)
cmdStr = '%s/build/bin/tmq_poll_test'%(buildPath)
tdLog.info(cmdStr)
os.system(cmdStr)
return return
def stop(self): def stop(self):

View File

@ -9,6 +9,7 @@ add_executable(tmq_td32187 tmq_td32187.c)
add_executable(tmq_ts5776 tmq_ts5776.c) add_executable(tmq_ts5776 tmq_ts5776.c)
add_executable(tmq_td32471 tmq_td32471.c) add_executable(tmq_td32471 tmq_td32471.c)
add_executable(tmq_td33798 tmq_td33798.c) add_executable(tmq_td33798 tmq_td33798.c)
add_executable(tmq_poll_test tmq_poll_test.c)
add_executable(tmq_write_raw_test tmq_write_raw_test.c) add_executable(tmq_write_raw_test tmq_write_raw_test.c)
add_executable(write_raw_block_test write_raw_block_test.c) add_executable(write_raw_block_test write_raw_block_test.c)
add_executable(sml_test sml_test.c) add_executable(sml_test sml_test.c)
@ -89,6 +90,13 @@ target_link_libraries(
PUBLIC common PUBLIC common
PUBLIC os PUBLIC os
) )
target_link_libraries(
tmq_poll_test
PUBLIC ${TAOS_LIB}
PUBLIC util
PUBLIC common
PUBLIC os
)
target_link_libraries( target_link_libraries(
tmq_td32526 tmq_td32526
PUBLIC ${TAOS_LIB} PUBLIC ${TAOS_LIB}

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "taos.h"
#include "tmsg.h"
#include "types.h"
TAOS_RES* pRes = NULL;
TAOS* pConn = NULL;
TAOS_RES* tmqmessage = NULL;
#define EXEC_SQL(sql) \
pRes = taos_query(pConn,sql);\
ASSERT(taos_errno(pRes) == 0);\
taos_free_result(pRes)
void init_env() {
EXEC_SQL("drop topic if exists topic_db");
EXEC_SQL("drop database if exists db_src");
EXEC_SQL("create database if not exists db_src vgroups 1 wal_retention_period 3600");
EXEC_SQL("use db_src");
EXEC_SQL("create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 nchar(8), t4 bool)");
EXEC_SQL("insert into ct3 using st1(t1) tags(3000) values(1626006833600, 5, 6, 'c')");
EXEC_SQL("create topic topic_db as database db_src");
}
tmq_t* build_consumer(bool testLongHeartBeat) {
tmq_conf_t* conf = tmq_conf_new();
tmq_conf_set(conf, "group.id", "tg2");
tmq_conf_set(conf, "client.id", "my app 1");
tmq_conf_set(conf, "td.connect.user", "root");
tmq_conf_set(conf, "td.connect.pass", "taosdata");
tmq_conf_set(conf, "msg.with.table.name", "true");
tmq_conf_set(conf, "enable.auto.commit", "true");
tmq_conf_set(conf, "auto.offset.reset", "earliest");
if (testLongHeartBeat){
ASSERT(tmq_conf_set(conf, "session.timeout.ms", "8000") == TMQ_CONF_OK);
ASSERT(tmq_conf_set(conf, "heartbeat.interval.ms", "100000") == TMQ_CONF_OK);
}
tmq_conf_set_auto_commit_cb(conf, NULL, NULL);
tmq_t* tmq = tmq_consumer_new(conf, NULL, 0);
ASSERT(tmq != NULL);
tmq_conf_destroy(conf);
return tmq;
}
tmq_list_t* build_topic_list() {
tmq_list_t* topic_list = tmq_list_new();
tmq_list_append(topic_list, "topic_db");
return topic_list;
}
void test_poll_continuity(tmq_t* tmq, tmq_list_t* topics) {
ASSERT ((tmq_subscribe(tmq, topics)) == 0);
tmqmessage = tmq_consumer_poll(tmq, 500);
ASSERT (tmqmessage != NULL);
taos_free_result(tmqmessage);
ASSERT (tmq_unsubscribe(tmq) == 0);
printf("unsubscribe success\n");
ASSERT (tmq_subscribe(tmq, topics) == 0);
printf("subscribe success\n");
tmqmessage = tmq_consumer_poll(tmq, 500);
ASSERT (tmqmessage == NULL);
taos_free_result(tmqmessage);
EXEC_SQL("insert into ct1 using st1(t1) tags(3000) values(1626006833600, 5, 6, 'c')");
printf("insert into ct1\n");
tmqmessage = tmq_consumer_poll(tmq, 500);
ASSERT (tmqmessage != NULL);
taos_free_result(tmqmessage);
}
void test_consumer_offline(tmq_t* tmq, tmq_list_t* topics) {
ASSERT ((tmq_subscribe(tmq, topics)) == 0);
tmqmessage = tmq_consumer_poll(tmq, 500);
ASSERT (tmqmessage != NULL);
taos_free_result(tmqmessage);
taosSsleep(15);
tmqmessage = tmq_consumer_poll(tmq, 500);
ASSERT (tmqmessage == NULL);
ASSERT (taos_errno(NULL) == TSDB_CODE_MND_CONSUMER_NOT_EXIST);
taos_free_result(tmqmessage);
}
int main(int argc, char* argv[]) {
pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT (pConn != NULL);
printf("test poll continuity\n");
for (int i = 0; i < 10; i++){
printf("-------run times:%d start---------\n", i);
init_env();
tmq_t* tmq = build_consumer(false);
tmq_list_t* topic_list = build_topic_list();
test_poll_continuity(tmq, topic_list);
ASSERT(tmq_consumer_close(tmq) == 0);
tmq_list_destroy(topic_list);
printf("-------run times:%d end---------\n\n", i);
}
// printf("\n\n\ntest consumer offline\n");
// init_env();
// tmq_t* tmq = build_consumer(true);
// tmq_list_t* topic_list = build_topic_list();
// test_consumer_offline(tmq, topic_list);
// ASSERT(tmq_consumer_close(tmq) == 0);
// tmq_list_destroy(topic_list);
taos_close(pConn);
}

View File

@ -76,7 +76,7 @@ void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) {
taosSsleep(5); taosSsleep(5);
TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 1000); TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 1000);
ASSERT(tmqmessage == NULL); ASSERT(tmqmessage == NULL);
ASSERT(taos_errno(NULL) == TSDB_CODE_TMQ_CONSUMER_MISMATCH); ASSERT(taos_errno(NULL) == TSDB_CODE_MND_CONSUMER_NOT_EXIST);
code = tmq_consumer_close(tmq); code = tmq_consumer_close(tmq);
if (code) if (code)