OceanBase V4.2 特性解析:用Values Statement 语法进行SQL优化

1. 背景

你是否也遭遇过这样的场景:在输出多行多列表格数据时,却受限于只能依赖多 UNION ALL 语句来实现。在实际的工程应用中,我们也观察到有些用户程序生成的 SQL 语句中含有大量的 UNION ALL,这种结构的 SQL 对于 OceanBase 数据库的内核来说并不友好,常常会导致内存和 CPU 的使用率显著上升。

OceanBase> SELECT 1, 2, 3 FROM DUAL UNION ALL SELECT 4, 5, 6 FROM DUAL UNION ALL SELECT 7, 8, 9 FROM DUAL; 
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        1 |        2 |        3 |
|        4 |        5 |        6 |
|        7 |        8 |        9 |
+----------+----------+----------+

OceanBase 在 V4.2.1 版本实现了 Values Statement 语法,它返回一行或多行作为表,可用作独立的 SQL 语句。换句话说,Values Statement提供了一种表数据的构造方式。例如:

OceanBase> VALUES ROW(1, 2, 3), ROW(4, 5, 6), ROW(7, 8, 9);
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        1 |        2 |        3 |
|        4 |        5 |        6 |
|        7 |        8 |        9 |
+----------+----------+----------+

2. 语法

其标准语法如下:

VALUES row_constructor_list [ORDER BY column_designator] [LIMIT number]

row_constructor_list:
    ROW(value_list)[, ROW(value_list)][, ...]

value_list:
    value[, value][, ...]

column_designator:
    column_index

Values Statement 语句由 VALUES 关键字组成,后跟一个或多个行构造函数的列表,以逗号分隔。行构造函数由 ROW() 行构造函数子句组成,该子句带有一个包含在括号中的一个或多个标量值的值列表。值可以是任何 MySQL 数据类型或标量值的表达式。最终组成多列多行的一张"表","表"的列默认指定了隐式命名:column_0、column_1、column_2 等,始终以 0 开头。如下面的一个简单例子:

OceanBase> VALUES ROW(1, -2, 3), ROW(5, 7, 9), ROW(4, 6, 8);
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
|        1 |       -2 |        3 |
|        5 |        7 |        9 |
|        4 |        6 |        8 |
+----------+----------+----------+

Values Statement 一列中允许使用不同类型的数值,如下所示:

OceanBase> VALUES ROW(1, -2, 'oceanbase'), ROW('a', 5, 'mysql'), ROW('222asda', 8, date'2020-12-01');
+----------+----------+--------------+
| column_0 | column_1 | column_2     |
+----------+----------+--------------+
| 1        |       -2 | oceanbase    |
| a        |        5 | mysql        |
| 222asda  |        8 | 2020-12-01   |
+----------+----------+--------------+

3. 使用场景

  1. 创建临时表格数据,可以使用一个表格数据替换多 UNION ALL。

例如:

SELECT 1, 2, 3 UNION ALL SELECT 4, 5, 6 UNION ALL SELECT 7, 8, 9; 
# 使用 Values Statement 表示临时表格数据为:
VALUES ROW(1, 2, 3), ROW(4, 5, 6), ROW(7, 8, 9);

例如:

CREATE TABLE t1 (type_a int, type_b int, type_c int);
SELECT CASE WHEN V.c1 = 1 AND t1.type_a = 1 THEN 'type_a'
            WHEN V.c1 = 2 AND t1.type_b = 1 THEN 'type_b'
            WHEN V.c1 = 3 AND t1.type_c = 1 THEN 'type_c'
            ELSE NULL
       END AS col_type
       FROM t1, (SELECT 1 AS c1 UNION ALL SELECT 2 UNION ALL SELECT 3) V;
# 使用 Values Statement 表示临时表格数据为:
SELECT CASE WHEN V.column_0 = 1 AND t1.type_a = 1 THEN 'type_a'
            WHEN V.column_0 = 2 AND t1.type_b = 1 THEN 'type_b'
            WHEN V.column_0 = 3 AND t1.type_c = 1 THEN 'type_c'
            ELSE NULL
       END AS col_type
       FROM t1, (VALUES ROW(1), ROW(2), ROW(3)) V;

2、快速创建表或视图。

例如:

CREATE TABLE t1 AS VALUES ROW(1, 2, 3), ROW(4, 5, 6), ROW(7, 8, 9);
CREATE VIEW v1 AS VALUES ROW(1, 2, 3), ROW(4, 5, 6), ROW(7, 8, 9);

4. Values Statement 能力和展望

除此之外,OceanBase V4.2.x 会将 Values Statement 用于优化器内部改写,优化大 IN/UNION 场景的执行性能,降低 SQL 资源消耗。例如:

1、将谓词中IN做改写,将过滤谓词变成了semi join,进一步改写为inner join,有了更多优化改写 的可能性。

SELECT * FROM t1 WHERE t1.c1 IN (1, 2, 3, 4);
# 内核改写为:
SELECT * FROM t1 SEMI JOIN (VALUES ROW(1), ROW(2), ROW(3), ROW(4)) V WHERE t1.c1 = V.column_0;

2、对于大量的常量union all/union 也能够改写

SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
# 内核改写为:
VALUES ROW(1, 2, 3)
相关推荐
OceanBase数据库官方博客17 小时前
OceanBase 中常用的查询语句
sql·oceanbase·分布式数据库·查询语句
OceanBase数据库官方博客3 天前
如何解决JAVA程序通过obloader并发导数导致系统夯住的问题 | OceanBase 运维实践
java·运维·oceanbase·分布式数据库
OceanBase数据库官方博客4 天前
如何配置 Flink CDC 连接 OceanBase 实现数据实时同步
大数据·flink·oceanbase·分布式数据库
OceanBase数据库官方博客4 天前
如何实现主备租户的无缝切换 | OceanBase应用实践
oceanbase·分布式数据库·高可用
靖顺5 天前
【OceanBase 诊断调优】—— ocp上针对OB租户CPU消耗计算逻辑
oceanbase
一名数据库爱好者6 天前
OceanBase 闪回查询
数据库·oceanbase·dba
OceanBase数据库官方博客6 天前
ODC 如何精确呈现SQL耗时 | OceanBase 开发者工具解析
sql·oceanbase·分布式数据库·开发者·生态工具
一名数据库爱好者6 天前
OceanBase单表恢复(4.2.1.8)
adb·oceanbase
靖顺6 天前
【OceanBase 诊断调优】—— OceanBase 数据库统计信息被禁用,状态为 broken 的原因和解决方法
数据库·oceanbase
OceanBase数据库官方博客10 天前
如何在 Ubuntu 上 部署 OceanBase
ubuntu·oceanbase·分布式数据库·安装部署