与标准 SQL 的主要差异
Contents
与标准 SQL 的主要差异#
本文将 OpenMLDB SQL 的主要使用方式(SELECT 查询语句)与标准 SQL (以 MySQL 支持的语法为例)进行比较,让有 SQL 使用经验的开发者快速上手 OpenMLDB SQL。
以下如无特殊说明,默认均为 OpenMLDB 版本:>= v0.7.1
支持总览#
下表根据 SELECT 语句元素对 OpenMLDB SQL 在三种执行模式下(关于执行模式参考使用流程和执行模式)与标准 SQL 整体性的差异做了汇总。OpenMLDB SQL 目前部分兼容标准 SQL,但考虑实际业务场景需求新增了部分语法,下表加粗部分为新增语法。
注:✓ 表示支持该语句,✕ 表示不支持。
OpenMLDB SQL |
OpenMLDB SQL |
OpenMLDB SQL |
标准 SQL |
备注 |
|
---|---|---|---|---|---|
WHERE 子句 |
✓ |
✓ |
✕ |
✓ |
部分功能可以通过带有 |
HAVING 子句 |
✓ |
✓ |
X |
✓ |
|
JOIN 子句 |
✓ |
✕ |
✓ |
✓ |
OpenMLDB 仅支持特有的 LAST JOIN |
GROUP BY 分组 |
✓ |
✕ |
✕ |
✓ |
|
ORDER BY 关键字 |
✓ |
✓ |
✓ |
✓ |
仅支持在 |
LIMIT 限制行数 |
✓ |
✓ |
✕ |
✓ |
|
WINDOW 子句 |
✓ |
✓ |
✓ |
✓ |
OpenMLDB 增加了特有的 WINDOW … UNION 和 WINDOW ATTRIBUTES 语法 |
WITH 子句 |
✕ |
✕ |
✕ |
✓ |
OpenMLDB 从版本 v0.7.2 开始支持 |
聚合函数 |
✓ |
✓ |
✓ |
✓ |
OpenMLDB 有较多扩展函数 |
差异详解#
差异维度#
与标准 SQL 比较,OpenMLDB SQL 的差异性主要会从三个维度进行说明:
执行模式:在三种不同执行模式下(离线模式,在线预览模式,在线请求模式),不同的 SQL 的支持程度不一样,需要分开考察。普遍的,为了最终可以让 SQL 实现实时计算,最终需要上线的业务 SQL 需要符合在线请求模式的要求。
子句组合:不同子句的组合会带来额外的限制,下文描述形式 A 应用于 B,表示 A 子句在 B 子句的结果上运行。比如 LIMIT 应用于 WHERE,则其 SQL 类似为:
SELECT * FROM (SELECT * FROM t1 WHERE id >= 2) LIMIT 2
。下文中的“表引用”是指FROM TableRef
,不是 subquery 也不是带有 JOIN/UNION 的复杂 FROM 子句。特殊限制:不归于以上两类的特殊限制,会进行单独说明,一般是由于功能支持不完善或者程序已知问题所引起。
扫描限制的配置#
为了避免用户误操作而影响到在线性能,OpenMLDB 有相关参数来限制在离线模式和在线预览模式下的全表扫描次数。如果打开了这些参数的限制,将会导致部分涉及到多个记录扫描的操作(比如 SELECT *, 聚合操作等)可能出现结果截断,而最终产生错误结果。注意,这些参数不会影响到在线请求模式的结果正确性。
相关参数会在 tablet 配置文件 conf/tablet.flags 里进行配置,详见文档配置文件 。影响到扫描限制的参数为:
最大扫描条数
--max_traverse_cnt
最大扫描 key 的个数
--max_traverse_pk_cnt
返回的结果大小限制
--scan_max_bytes_size
预计在 v0.7.3 以及以后版本中,以上参数的默认值都为 0,即不做相关限制。之前的版本需要注意相关参数的设置。
WHERE 子句#
应用于 |
离线模式 |
在线预览模式 |
在线请求模式 |
---|---|---|---|
表引用 |
✓ |
✓ |
✕ |
LAST JOIN |
✓ |
✓ |
✕ |
子查询 / WITH 子句 |
✓ |
✓ |
✕ |
虽然在线请求模式无法支持支持 WHERE
子句,但是部分功能可以通过带有 _where
后缀的计算函数实现,比如 count_where
, avg_wgere
等,详情查看内置计算函数文档。
LIMIT 子句#
后面跟一个 INT literal, 不支持其它表达式,表示返回数据的最大行数。LIMIT 不支持上线。
应用于 |
离线模式 |
在线预览模式 |
在线请求模式 |
---|---|---|---|
表引用 |
✓ |
✓ |
✕ |
WHERE |
✓ |
✓ |
✕ |
WINDOW |
✓ |
✓ |
✕ |
LAST JOIN |
✓ |
✓ |
✕ |
GROUP BY & HAVING |
✕ |
✓ |
X |
WINDOW 子句#
WINDOW 子句和 GROUP BY & HAVING 子句不支持同时使用。上线时 WINDOW 的输入表必须是物理表或者对物理表的简单列筛选和 LAST JOIN 拼接(简单列筛选为 select list 只有列引用或者列的重命名,没有其它表达式),具体支持参照下表,未列出情况均为不支持。
应用于 |
离线模式 |
在线预览模式 |
在线请求模式 |
---|---|---|---|
表引用 |
✓ |
✓ |
✓ |
GROUP BY & HAVING |
✕ |
✕ |
✕ |
LAST JOIN |
✓ |
✓ |
✓ |
子查询,仅以下情况: |
✓ |
✓ |
✓ |
特殊限制:
在线请求模式下,WINDOW 的输入是 LAST JOIN 或者子查询内的 LAST JOIN, 注意窗口的定义里
PARTITION BY
&ORDER BY
的列都必须来自 JOIN 最左边的表。
GROUP BY & HAVING 子句#
GROUP BY 语句,目前仍为实验性功能,仅支持输入表是一张物理表, 其它情况不支持。GROUP BY 不支持上线。
应用于 |
离线模式 |
在线预览模式 |
在线请求模式 |
---|---|---|---|
表引用 |
✓ |
✓ |
✕ |
WHERE |
✕ |
✕ |
✕ |
LAST JOIN |
✕ |
✕ |
✕ |
子查询 |
✕ |
✕ |
✕ |
JOIN 子句(LAST JOIN)#
OpenMLDB 仅支持 LAST JOIN 一种 JOIN 语法,详细描述参考扩展语法的 LAST JOIN 部分。JOIN 有左右两个输入,在线请求模式下,支持两个输入为物理表,或者特定的子查询,详见表格,未列出情况不支持。
应用于 |
离线模式 |
在线预览模式 |
在线请求模式 |
---|---|---|---|
两个表引用 |
✓ |
✕ |
✓ |
子查询, 仅包括: |
✓ |
✓ |
✓ |
特殊限制:
关于特定子查询的 LAST JOIN 上线,还有额外要求,详见上线要求 。
在线预览模式下暂不支持 LAST JOIN
WITH 子句#
OpenMLDB (>= v0.7.2) 支持非递归的 WITH 子句。WITH 子句等价于其它子句应用于子查询时的语义,WITH 语句的支持情况,可参照其对应子查询写法下,上述表格的说明。
特殊限制:
无
ORDER BY 关键字#
排序关键字 ORDER BY
仅在窗口定义 WINDOW
和拼表操作 LAST JOIN
子句内部被支持,并且不支持倒排序关键字 DESC
。参见 WINDOW 子句和 LAST JOIN 子句内的相关说明。
聚合函数#
聚合函数可应用于全表或窗口。三种模式下均支持窗口聚合查询;全表聚合查询仅在在线预览模式下支持,离线和在线请求模式不支持。
特殊限制:
OpenMLDB v0.6.0 开始支持在线预览模式的全表聚合,但注意所描述的扫描限制配置。
OpenMLDB 有较多的聚合函数扩展,请查看产品文档具体查询所支持的函数 OpenMLDB 内置函数。
扩展语法#
OpenMLDB 主要对 WINDOW
以及 LAST JOIN
语句进行了深度定制化开发,本节将对这两个语法进行详细说明。
WINDOW 子句#
在 OpenMLDB 里使用到的一个典型的 WINDOW 语句一般会包含以下元素:
数据定义:通过
PARTITION BY
定义窗口内数据数据排序:通过
ORDER BY
定义窗口内数据排序范围定义:通过
PRECEDING
,CURRENT ROW
,UNBOUNDED
定义时间延展方向范围单位:通过
ROWS
,ROWS_RANGE
定义窗口滑动范围的单位窗口属性:OpenMLDB 特有的窗口属性定义,包括
MAXSIZE
,EXECLUDE CURRENT_ROW
,EXCLUDE CURRENT_TIME
,INSTANCE_NOT_IN_WINDOW
多表定义:通过扩展语法
WINDOW ... UNION
定义是否需要进行跨表数据源拼接
关于 WINDOW 详细语法,请参考 WINDOW 文档。
语句元素 |
支持语法 |
说明 |
必需 ? |
---|---|---|---|
数据定义 |
PARTITION BY |
可支持多列 |
✓ |
数据排序 |
ORDER BY |
仅支持对单一列排序 |
✓ |
范围定义 |
|
必须给定上下边界 |
✓ |
范围单位 |
ROWS |
ROWS_RANGE 为扩展语法,其定义的窗口边界属性等价于标准 SQL 的 RANGE 类型窗口,支持用数值或者带时间单位的数值定义窗口边界,后者为拓展语法。 |
✓ |
窗口属性(扩展) |
MAXSIZE |
MAXSIZE 只对 ROWS_RANGE 有效 |
- |
多表定义(扩展) |
实际使用中语法形态较为复杂,参考: |
允许合并多个表 |
- |
匿名窗口 |
- |
必须包括 PARTITION BY、ORDER BY、以及窗口范围定义 |
- |
特殊限制#
在线预览模式或者离线模式下,WINDOW 的输入是 LIMIT 或者 WHERE 子句时,在某些情况下目前有已知问题, 不建议使用。
窗口定义举例#
定义 ROWS
类型窗口,窗口范围是前 1000 行到当前行:
SELECT
sum(col2) OVER w1 as w1_col2_sum
FROM
t1WINDOW w1 AS (
PARTITION BY col1
ORDER BY
col5 ROWS BETWEEN 1000 PRECEDING
AND CURRENT ROW
);
定义 ROWS_RANGE
类型窗口,窗口范围是当前行前 10 秒的所有行,以及当前行:
SELECT
sum(col2) OVER w1 as w1_col2_sum
FROM
t1WINDOW w1 AS (
PARTITION BY col1
ORDER BY
col5 ROWS_RANGE BETWEEN 10s PRECEDING
AND CURRENT ROW
);
定义一个 ROWS
类型窗口,窗口范围是前1000行到当前行。 除了当前行以外窗口内不包含当前时刻的其他数据:
SELECT
sum(col2) OVER w1 as w1_col2_sum
FROM
t1 WINDOW w1 AS (
PARTITION BY col1
ORDER BY
col5 ROWS BETWEEN 1000 PRECEDING
AND CURRENT ROW EXCLUDE CURRENT_TIME
);
定义一个 ROWS_RANGE
类型窗口,窗口范围为当前时间到过去 10 秒,但是不包含当前请求行:
SELECT
sum(col2) OVER w1 as w1_col2_sum
FROM
t1 WINDOW w1 AS (
PARTITION BY col1
ORDER BY
col5 ROWS_RANGE BETWEEN 10s PRECEDING
AND CURRENT ROW EXCLUDE CURRENT_ROW
);
匿名窗口:
SELECT
id,
pk1,
col1,
std_ts,
sum(col1) OVER (
PARTITION BY pk1
ORDER BY
std_ts ROWS BETWEEN 1 PRECEDING
AND CURRENT ROW
) as w1_col1_sumfrom t1;
WINDOW … UNION 举例#
在实际开发中,较多的应用的数据是存放在多个表格中,在这种情况下,一般会使用 WINDOW … UNION 的语法进行跨表的聚合操作。请参考跨表特征开发教程关于“ 副表多行聚合特征”部分。
LAST JOIN 子句#
关于 LAST JOIN 详细语法规范,请参考 LAST JOIN 文档。
语句元素 |
支持语法 |
说明 |
必需? |
---|---|---|---|
ON |
✓ |
列类型支持:BOOL, INT16, INT32, INT64, STRING, DATE, TIMESTAMP |
✓ |
USING |
不支持 |
- |
- |
ORDER BY |
✓ |
后面只能接单列列类型 : INT16, INT32, INT64, TIMESTAMP |
- |
LAST JOIN 举例#
SELECT
*
FROM
t1
LAST JOIN t2 ON t1.col1 = t2.col1;