Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
76114905
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
76114905
编写于
8月 08, 2022
作者:
J
jiajingbin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
docs: update 06-stream.md for stream-computing
上级
922593bc
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
65 addition
and
133 deletion
+65
-133
docs/zh/07-develop/06-stream.md
docs/zh/07-develop/06-stream.md
+65
-133
未找到文件。
docs/zh/07-develop/06-stream.md
浏览文件 @
76114905
...
...
@@ -7,7 +7,7 @@ title: 流式计算
在时序数据的处理中,经常要对原始数据进行清洗、预处理,再使用时序数据库进行长久的储存。用户通常需要在时序数据库之外再搭建 Kafka、Flink、Spark 等流计算处理引擎,增加了用户的开发成本和维护成本。
使用 TDengine 3.0 的流式计算引擎能够最大限度的减少对这些额外中间件的依赖,真正将数据的写入、预处理、长期存储、复杂分析、实时计算、实时报警触发等功能融为一体,并且,所有这些任务只需要使用 SQL 完成,极大降低了用户的学习成本、使用成本。
##
创建流
##
流式计算的创建
```
sql
CREATE
STREAM
[
IF
NOT
EXISTS
]
stream_name
[
stream_options
]
INTO
stb_name
AS
subquery
...
...
@@ -16,96 +16,13 @@ stream_options: {
WATERMARK
time
IGNORE
EXPIRED
}
其中
subquery
是
select
普通查询语法的子集
:
subquery
:
SELECT
[
DISTINCT
]
select_list
from_clause
[
WHERE
condition
]
[
PARTITION
BY
tag_list
]
[
window_clause
]
[
group_by_clause
]
不支持
order_by
,
limit
,
slimit
,
fill
语句
```
### 流式计算与窗口切分查询
窗口子句语法如下:
```
sql
window_clause
:
{
SESSION
(
ts_col
,
tol_val
)
|
STATE_WINDOW
(
col
)
|
INTERVAL
(
interval_val
[,
interval_offset
])
[
SLIDING
(
sliding_val
)]
}
```
其中,SESSION 是会话窗口,tol_val 是时间间隔的最大范围。在 tol_val 时间间隔范围内的数据都属于同一个窗口,如果连续的两条数据的时间超过 tol_val,则自动开启下一个窗口;
STATE_WINDOW 是状态窗口,产生的连续记录如果具有相同的状态量数值则归属于同一个状态窗口,数值改变后该窗口关闭;
INTERVAL 是时间窗口,用于产生相等时间周期的窗口,查询过滤、聚合等操作按照每个时间窗口为独立的单位执行;
为了便于理解,下面以 interval(10s) 为例,假设事件时间为 "2022-08-06 00:00:01",对应的窗口为 "2022-08-06 00:00:00" ~ "2022-08-06 00:00:10"(窗口 A),那么下一个窗口为 "2022-08-06 00:00:10" ~ "2022-08-06 00:00:20"(窗口 B)。
### 流式计算的触发模式
在创建流时,可以通过 TRIGGER 指令指定流式计算的触发模式。
对于非窗口计算,流式计算的触发是实时的;
对于窗口计算,目前提供 3 种触发模式:
1.
AT_ONCE:写入立即触发,窗口 A 和窗口 B 的数据写入后均可以立即触发计算;
2.
WINDOW_CLOSE:窗口关闭时触发(可配合 WATERMARK 使用,详见
[
流式计算的乱序数据容忍策略
](
#流式计算的乱序数据容忍策略
)
,当窗口 B 的数据到达时,窗口 A 才会关闭并触发 WINDOW_CLOSE;
3.
MAX_DELAY time:若窗口 A 关闭,则触发计算。若窗口 B 未关闭,且未关闭时长超过 MAX_DELAY 指定的时间,则触发计算。
由于窗口关闭是由事件时间决定的,如事件流中断、或持续延迟,则事件时间无法更新,可能导致无法得到最新的计算结果;
因此,流式计算提供了以事件时间结合处理时间计算的 MAX_DELAY 触发模式;
MAX_DELAY 模式在窗口关闭时或者数据写入后计算触发的时间超过 MAX_DELAY 指定的时间,会立即触发计算。
### 流式计算的乱序数据容忍策略
在创建流时,可以在 stream_options 中指定 WATERMARK;
流式计算通过 WATERMARK 来度量对乱序数据的容忍程度,WATERMARK 默认为 0。
T = 最新事件时间 - WATERMARK
每批到来的数据都会以上述公式更新窗口关闭时间,并将窗口结束时间 < T 的所有打开的窗口关闭,若触发模式为 WINDOW_CLOSE 或 MAX_DELAY,则推送窗口聚合结果。
以上面的 WINDOW_CLOSE 为例,如果设置了 WATERMARK 15s,那么窗口 A 和 B 均会延迟推送计算结果,当最新事件时间为 "2022-08-06 00:00:25" 时会推送窗口 A 的结果,当最新事件时间为 "2022-08-06 00:00:35" 时会推送窗口 B 的结果。
### 流式计算的过期数据处理策略
对于已关闭的窗口,再次落入该窗口中的数据被标记为过期数据,对于过期数据,流式计算提供两种处理方式:
1.
直接丢弃:这是常见流式计算引擎提供的默认(甚至是唯一)计算模式;
2.
重新计算:从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果;
模式 1 创建流时需要在 stream_options 中配置 IGNORE EXPIRED,对于已经关闭的窗口,再次落入该窗口的乱序数据会被直接丢弃;
详细的语法规则参考
[
流式计算
](
/taos-sql/stream/
)
无论在哪种模式下,WATERMARK 都应该被妥善设置,来得到正确结果(直接丢弃模式)或避免频繁触发重算带来的性能开销(重新计算模式)。
## 示例一
## 流式计算的展示
```
sql
SHOW
STREAMS
;
```
## 流式计算的删除
```
sql
DROP
STREAM
[
IF
EXISTS
]
stream_name
;
```
## 使用案例
通过以下案例,进一步了解 TDengine 流计算的使用
查找过去 12 小时电表电压大于 220V 的记录条数和电流的最大值,并对采集的数据按时间窗口聚合。
### 创建 DB 和原始数据表
...
...
@@ -115,79 +32,94 @@ DROP STREAM [IF EXISTS] stream_name;
drop
database
if
exists
stream_db
;
create
database
stream_db
;
create
table
stream_db
.
stb
(
ts
timestamp
,
c1
int
,
c2
float
,
c3
varchar
(
16
))
tags
(
t1
int
,
t3
varchar
(
16
)
);
create
table
stream_db
.
ctb0
using
stream_db
.
stb
tags
(
0
,
"subtable0"
);
create
table
stream_db
.
ctb1
using
stream_db
.
stb
tags
(
1
,
"subtable1"
);
create
table
stream_db
.
ctb2
using
stream_db
.
stb
tags
(
2
,
"subtable2"
);
create
table
stream_db
.
ctb3
using
stream_db
.
stb
tags
(
3
,
"subtable3"
);
create
stable
stream_db
.
meters
(
ts
timestamp
,
current
float
,
voltage
int
)
TAGS
(
location
varchar
(
64
),
groupId
int
);
create
table
stream_db
.
d1001
using
stream_db
.
meters
tags
(
"beijing"
,
1
);
create
table
stream_db
.
d1002
using
stream_db
.
meters
tags
(
"guangzhou"
,
2
);
create
table
stream_db
.
d1003
using
stream_db
.
meters
tags
(
"shanghai"
,
3
);
```
### 创建流
case1. 创建流实现数据过滤
```
sql
create
stream
stream1
into
stream_db
.
stream1_output_stb
as
select
*
from
stream_db
.
stb
where
c1
>
0
and
c2
!=
10
and
c3
is
not
Null
;
create
stream
stream1
into
stream_db
.
stream1_output_stb
as
select
_wstart
as
start
,
count
(
voltage
),
max
(
current
)
from
stream_db
.
meters
where
voltage
>
220
and
ts
>
now
-
12
h
interval
(
1
h
)
;
```
case2. 创建流实现标量函数的数据转换
### 写入数据
```
sql
create
stream
stream2
into
stream_db
.
stream2_output_stb
as
select
ts
,
abs
(
c2
),
char_length
(
c3
),
cast
(
c1
as
binary
(
16
)),
timezone
()
from
stream_db
.
stb
partition
by
tbname
;
insert
into
stream_db
.
d1001
values
(
now
-
14
h
,
10
.
3
,
210
);
insert
into
stream_db
.
d1001
values
(
now
-
13
h
,
13
.
5
,
226
);
insert
into
stream_db
.
d1001
values
(
now
-
12
h
,
12
.
5
,
221
);
insert
into
stream_db
.
d1002
values
(
now
-
11
h
,
14
.
7
,
221
);
insert
into
stream_db
.
d1002
values
(
now
-
10
h
,
10
.
5
,
219
);
insert
into
stream_db
.
d1002
values
(
now
-
9
h
,
11
.
2
,
217
);
insert
into
stream_db
.
d1003
values
(
now
-
8
h
,
11
.
5
,
222
);
insert
into
stream_db
.
d1003
values
(
now
-
7
h
,
12
.
3
,
227
);
insert
into
stream_db
.
d1003
values
(
now
-
6
h
,
12
.
3
,
215
);
```
case3. 创建流实现数据降采样
### 查询以观查结果
```
sql
create
stream
stream3
into
stream_db
.
stream3_output_stb
as
select
_wstart
as
start
,
min
(
c1
),
max
(
c2
),
count
(
c3
)
from
stream_db
.
stb
interval
(
10
s
);
taos
>
select
*
from
stream_db
.
stream1_output_stb
;
start
|
count
(
voltage
)
|
max
(
current
)
|
group_id
|
=================================================================================================
2022
-
08
-
08
08
:
00
:
00
.
000
|
1
|
14
.
70000
|
0
|
2022
-
08
-
08
11
:
00
:
00
.
000
|
1
|
11
.
50000
|
0
|
2022
-
08
-
08
12
:
00
:
00
.
000
|
1
|
12
.
30000
|
0
|
Query
OK
,
3
rows
in
database
(
0
.
008239
s
)
```
case4. 通过 trigger window_close 控制流的触发频率
## 示例二
查询所有电表中电压等于 220V 的数据,对过滤出的电表电流数据进行四舍五入运算,同时将主键时间戳列转换为 bigint 类型,并对采集的数据按表名分组。
```
sql
create
stream
stream4
trigger
window_close
into
stream_db
.
stream4_output_stb
as
select
_wstart
as
start
,
min
(
c1
),
max
(
c2
),
count
(
c3
)
from
stream_db
.
stb
interval
(
10
s
);
```
case4. 通过 trigger max_delay 控制流的触发频率
### 创建 DB 和原始数据表
首先准备数据,完成建库、建一张超级表和多张子表操作
```
sql
create
stream
stream5
trigger
max_delay
3
s
into
stream_db
.
stream5_output_stb
as
select
_wstart
as
start
,
min
(
c1
),
max
(
c2
),
count
(
c3
)
from
stream_db
.
stb
interval
(
10
s
)
;
```
drop
database
if
exists
stream_db
;
create
database
stream_db
;
c
ase6. 通过 watermark 实现乱序数据容忍
c
reate
stable
stream_db
.
meters
(
ts
timestamp
,
current
float
,
voltage
int
)
TAGS
(
location
varchar
(
64
),
groupId
int
);
```
sql
create
stream
stream6
trigger
window_close
watermark
15
s
into
stream_db
.
stream6_output_stb
as
select
_wstart
as
start
,
min
(
c1
),
max
(
c2
),
count
(
c3
)
from
stream_db
.
stb
interval
(
10
s
);
create
table
stream_db
.
d1001
using
stream_db
.
meters
tags
(
"beijing"
,
1
);
create
table
stream_db
.
d1002
using
stream_db
.
meters
tags
(
"shanghai"
,
2
);
create
table
stream_db
.
d1003
using
stream_db
.
meters
tags
(
"beijing"
,
2
);
create
table
stream_db
.
d1004
using
stream_db
.
meters
tags
(
"tianjin"
,
3
);
create
table
stream_db
.
d1005
using
stream_db
.
meters
tags
(
"shanghai"
,
1
);
```
case7. 通过 ignore expired 实现乱序数据丢弃
### 创建流
```
sql
create
stream
stream
7
trigger
at_once
ignore
expired
into
stream_db
.
stream7_output_stb
as
select
_wstart
as
start
,
min
(
c1
),
max
(
c2
),
count
(
c3
)
from
stream_db
.
stb
interval
(
10
s
)
;
create
stream
stream
2
into
stream_db
.
stream2_output_stb
as
select
ts
,
cast
(
ts
as
bigint
),
round
(
current
),
location
from
stream_db
.
meters
where
voltage
=
220
partition
by
tbname
;
```
### 写入数据
```
sql
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:01"
,
1
,
1
,
'a1'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:07"
,
7
,
7
,
'a7'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:11"
,
11
,
11
,
'a11'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:21"
,
21
,
21
,
'a21'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:24"
,
24
,
24
,
'a24'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:25"
,
25
,
25
,
'a25'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:34"
,
34
,
34
,
'a34'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:35"
,
35
,
35
,
'a35'
);
insert
into
stream_db
.
ctb0
values
(
"2022-08-13 00:00:02"
,
2
,
2
,
'a2'
);
insert
into
stream_db
.
d1001
values
(
now
-
14
h
,
10
.
3
,
210
);
insert
into
stream_db
.
d1001
values
(
now
-
13
h
,
13
.
5
,
220
);
insert
into
stream_db
.
d1002
values
(
now
-
12
h
,
14
.
7
,
218
);
insert
into
stream_db
.
d1002
values
(
now
-
11
h
,
10
.
5
,
220
);
insert
into
stream_db
.
d1003
values
(
now
-
10
h
,
11
.
5
,
220
);
insert
into
stream_db
.
d1003
values
(
now
-
9
h
,
12
.
3
,
215
);
insert
into
stream_db
.
d1004
values
(
now
-
8
h
,
11
.
5
,
220
);
insert
into
stream_db
.
d1004
values
(
now
-
7
h
,
15
.
3
,
217
);
insert
into
stream_db
.
d1005
values
(
now
-
6
h
,
16
.
5
,
216
);
insert
into
stream_db
.
d1005
values
(
now
-
5
h
,
12
.
3
,
220
);
```
### 查询以观查结果
```
sql
select
*
from
stream_db
.
stream1_output_stb
;
select
*
from
stream_db
.
stream2_output_stb
;
select
*
from
stream_db
.
stream3_output_stb
;
select
*
from
stream_db
.
stream4_output_stb
;
select
*
from
stream_db
.
stream5_output_stb
;
select
*
from
stream_db
.
stream6_output_stb
;
select
*
from
stream_db
.
stream7_output_stb
;
taos
>
select
*
from
stream_db
.
stream2_output_stb
;
ts
|
cast
(
ts
as
bigint
)
|
round
(
current
)
|
location
|
group_id
|
==================================================================================================================================
2022
-
08
-
08
09
:
29
:
55
.
557
|
1659922195557
|
12
.
00000
|
beijing
|
7226905450883977166
|
2022
-
08
-
08
11
:
29
:
55
.
570
|
1659929395570
|
12
.
00000
|
tianjin
|
7226905450884501455
|
2022
-
08
-
08
08
:
29
:
55
.
549
|
1659918595549
|
11
.
00000
|
shanghai
|
7226905450883452877
|
2022
-
08
-
08
06
:
29
:
55
.
534
|
1659911395534
|
14
.
00000
|
beijing
|
7226905450882928588
|
2022
-
08
-
08
14
:
29
:
56
.
175
|
1659940196175
|
12
.
00000
|
shanghai
|
7226905450895708112
|
Query
OK
,
5
rows
in
database
(
0
.
015235
s
)
```
## 示例三
...待续
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录