MATERIAL 算子用于物化下层算子输出的数据。
OceanBase 数据库以流式数据执行计划,但有时算子需要等待下层算子输出所有数据后才能够开始执行,所以需要在下方添加一个 MATERIAL 算子物化所有的数据。或者在子计划需要重复执行的时候,使用 MATERIAL 算子可以避免重复执行。
如下示例中,t1 表与 t2 表执行 NESTED LOOP JOIN 运算时,右表需要重复扫描,可以在右表有一个 MATERIAL 算子,保存 t2 表的所有数据。
obclient>CREATE TABLE t1(c1 INT, c2 INT, c3 INT);
Query OK, 0 rows affected (0.12 sec)
obclient>CREATE TABLE t2(c1 INT ,c2 INT ,c3 INT);
Query OK, 0 rows affected (0.12 sec)
obclient>EXPLAIN SELECT /*+ORDERED USE_NL(T2)*/* FROM t1,t2
WHERE t1.c1=t2.c1\G;
*************************** 1. row ***************************
Query Plan:
===========================================
|ID|OPERATOR |NAME|EST. ROWS|COST |
-------------------------------------------
|0 |NESTED-LOOP JOIN| |2970 |277377|
|1 | TABLE SCAN |t1 |3 |37 |
|2 | MATERIAL | |100000 |176342|
|3 | TABLE SCAN |t2 |100000 |70683 |
===========================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter(nil),
conds([t1.c1 = t2.c1]), nl_params_(nil)
1 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil),
access([t1.c1], [t1.c2], [t1.c3]), partitions(p0)
2 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil)
3 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil),
access([t2.c1], [t2.c2], [t2.c3]), partitions(p0)
上述示例中,执行计划展示中 2 号算子 MATERIAL 的功能是保存 t2 表的数据,以避免每次联接都从磁盘扫描 t2 表的数据。执行计划展示中的 outputs & filters 详细展示了 MATERIAL 算子的输出信息如下:
信息名称 | 含义 |
---|---|
output | 该算子输出的表达式。 其中 rownum() 表示 ROWNUM 对应的表达式。 |
filter | 该算子上的过滤条件。 由于示例中 MATERIAL 算子没有设置 filter,所以为 nil。 |