Calcite中的流式SQL
作者:Ransom0512 发布时间:[ 2017/1/19 13:40:58 ] 推荐标签:SQL Server 数据库
Calcite中的流式SQL总体设计思路
总体语法应该兼容SQL,这个是和目前流处理SQL的发展趋势是一致的。
如果部分功能标准SQL中没有包含,则尽量采用 业界标杆(Oracle) 。比如模式匹配的功能,目前流处理中还没有针对语法达成共识,那么在设计上,采用Oracle data warehouse的Match Recognize的方式。还有滑窗功能。
如果还有功能目前业界标杆都没有,那么通过函数的方式拓展,翻滚窗口和跳动窗口,这两个窗口在标准SQL中都是不包含的,所以采用了Ceil,Tumble,Hop等函数的方式来实现功能。
总体思路是 在兼容标准SQL的基础上做尽可能少的拓展,保证语义和标准SQL一致,尽大可能减少私有化的语法 。
Calcite StreamSQL说明
1、在DDL中明确定义schema是流Or表,TODO:官网没有示例,待补充
比如有三张schema:
Orders (rowtime, productId, orderId, units) - 既是表,又是流
Products (rowtime, productId, name) - 表
Shipments (rowtime, orderId) - 流
2、查询中如果包含Stream关键字,是流式查询,如果不包含,是表查询。表查询可以马上返回结果并结束,流式查询只会输出结果但并不结束。
比如下面一个流查询示例:
SELECT STREAM *
FROM Orders;
rowtime | productId | orderId | units
----------+-----------+---------+-------
10:17:00 | 30 | 5 | 4
10:17:05 | 10 | 6 | 1
10:18:05 | 20 | 7 | 2
10:18:07 | 30 | 8 | 20
11:02:00 | 10 | 9 | 6
11:04:00 | 10 | 10 | 1
11:09:30 | 40 | 11 | 12
11:24:11 | 10 | 12 | 4
表查询示例:
SELECT *
FROM Orders;
rowtime | productId | orderId | units
----------+-----------+---------+-------
08:30:00 | 10 | 1 | 3
08:45:10 | 20 | 2 | 1
09:12:21 | 10 | 3 | 10
09:27:44 | 30 | 4 | 2
4 records returned.
流和表的查询不能混用,否则会报错
SELECT * FROM Shipments;
ERROR: Cannot convert stream 'SHIPMENTS' to a table
SELECT STREAM * FROM Products;
ERROR: Cannot convert table 'PRODUCTS' to a stream
1、其他过滤,排序,having等操作和标准sql一致,不再举例。
2、子查询只需要在外层语句写Stream关键字即可,内层写了无效。
如:
SELECT STREAM rowtime, productId
FROM (
SELECT TUMBLE_END(rowtime, INTERVAL '1' HOUR) AS rowtime,
productId,
COUNT(*) AS c,
SUM(units) AS su
FROM Orders
GROUP BY TUMBLE(rowtime, INTERVAL '1' HOUR), productId)
WHERE c > 2 OR su > 10;
rowtime | productId
----------+-----------
10:00:00 | 30
11:00:00 | 10
11:00:00 | 40
窗口功能说明
翻滚窗(Tumbling window)
两个窗口之间数据没有重叠。
SELECT STREAM CEIL(rowtime TO HOUR) AS rowtime,
productId,
COUNT(*) AS c,
SUM(units) AS units
FROM Orders
GROUP BY CEIL(rowtime TO HOUR), productId;
rowtime | productId | c | units
----------+-----------+---------+-------
11:00:00 | 30 | 2 | 24
11:00:00 | 10 | 1 | 1
11:00:00 | 20 | 1 | 7
12:00:00 | 10 | 3 | 11
12:00:00 | 40 | 1 | 12
该示例每个小时结束的时候,输出这个小时的统计结果,11点整,输出1点的统计结果。以事件为驱动,内部不包含定时器。
下面的例子和上面的例子等价
SELECT STREAM TUMBLE_END(rowtime, INTERVAL '1' HOUR) AS rowtime,
productId,
COUNT(*) AS c,
SUM(units) AS units
FROM Orders
GROUP BY TUMBLE(rowtime, INTERVAL '1' HOUR), productId;
rowtime | productId | c | units
----------+-----------+---------+-------
11:00:00 | 30 | 2 | 24
11:00:00 | 10 | 1 | 1
11:00:00 | 20 | 1 | 7
12:00:00 | 10 | 3 | 11
12:00:00 | 40 | 1 | 12
又比如,需要没半个小时输出一次结果,以12分钟为对齐时间,
SELECT STREAM
TUMBLE_END(rowtime, INTERVAL '30' MINUTE, TIME '0:12') AS rowtime,
productId,
COUNT(*) AS c,
SUM(units) AS units
FROM Orders
GROUP BY TUMBLE(rowtime, INTERVAL '30' MINUTE, TIME '0:12'),
productId;
rowtime | productId | c | units
----------+-----------+---------+-------
10:42:00 | 30 | 2 | 24
10:42:00 | 10 | 1 | 1
10:42:00 | 20 | 1 | 7
11:12:00 | 10 | 2 | 7
11:12:00 | 40 | 1 | 12
11:42:00 | 10 | 1 | 4
跳动窗(HOP window)
两个窗口之间的数据有一定重叠。
跳动窗口是广义化的翻滚窗,允许数据在窗口中保存更长时间。
比如下面的例子,数据输出时间为11:00,但是其中还包含08:00到11:00的数据,以及09:00到12:00的数据,一个输入行对应三个输出行。
SELECT STREAM
HOP_END(rowtime, INTERVAL '1' HOUR, INTERVAL '3' HOUR) AS rowtime,
COUNT(*) AS c,
SUM(units) AS units
FROM Orders
GROUP BY HOP(rowtime, INTERVAL '1' HOUR, INTERVAL '3' HOUR);
rowtime | c | units
----------+----------+-------
11:00:00 | 4 | 27
12:00:00 | 8 | 50
滑动窗(sliding window)
Calcite中的滑动窗采用标准的Over方式,直接套用了标准SQL中的分析函数。
SELECT STREAM rowtime,
productId,
units,
SUM(units) OVER (ORDER BY rowtime RANGE INTERVAL '1' HOUR PRECEDING) unitsLastHour
FROM Orders;
下面的一个例子展示了过去10分钟的平均订单大小和上周平均订单的比较数据
SELECT STREAM *
FROM (
SELECT STREAM rowtime,
productId,
units,
AVG(units) OVER product (RANGE INTERVAL '10' MINUTE PRECEDING) AS m10,
AVG(units) OVER product (RANGE INTERVAL '7' DAY PRECEDING) AS d7
FROM Orders
WINDOW product AS (
ORDER BY rowtime
PARTITION BY productId))
WHERE m10 > d7;
在这个例子中,使用Window子句来定义部分窗口,然后在每个OVER子句中在进行细化。初次之外,还可以在window子句中定义所有的窗口。
这种实现方式中,在后台同时维护了两张表,10分钟和7天的窗口数据。你可以直接访问到这些表,不需要做显示的查询。
这种语法还可以实现其他一些功能:
* 行组窗口
* 引用尚未到达的行,流将等待,直到它们到达。
* 可以支持其他RANK等统计分析函数
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11