MATERIAL 算子用于物化下层算子输出的数据。

    OceanBase 数据库以流式数据执行计划,但有时算子需要等待下层算子输出所有数据后才能够开始执行,所以需要在下方添加一个 MATERIAL 算子物化所有的数据。或者在子计划需要重复执行的时候,使用 MATERIAL 算子可以避免重复执行。

    如下示例中,t1 表与 t2 表执行 NESTED LOOP JOIN 运算时,右表需要重复扫描,可以在右表有一个 MATERIAL 算子,保存 t2 表的所有数据。

    1. obclient>CREATE TABLE t1(c1 INT, c2 INT, c3 INT);
    2. Query OK, 0 rows affected (0.12 sec)
    3. obclient>CREATE TABLE t2(c1 INT ,c2 INT ,c3 INT);
    4. Query OK, 0 rows affected (0.12 sec)
    5. obclient>EXPLAIN SELECT /*+ORDERED USE_NL(T2)*/* FROM t1,t2
    6. WHERE t1.c1=t2.c1\G;
    7. *************************** 1. row ***************************
    8. Query Plan:
    9. ===========================================
    10. |ID|OPERATOR |NAME|EST. ROWS|COST |
    11. -------------------------------------------
    12. |0 |NESTED-LOOP JOIN| |2970 |277377|
    13. |1 | TABLE SCAN |t1 |3 |37 |
    14. |2 | MATERIAL | |100000 |176342|
    15. |3 | TABLE SCAN |t2 |100000 |70683 |
    16. ===========================================
    17. Outputs & filters:
    18. -------------------------------------
    19. 0 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter(nil),
    20. conds([t1.c1 = t2.c1]), nl_params_(nil)
    21. 1 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil),
    22. access([t1.c1], [t1.c2], [t1.c3]), partitions(p0)
    23. 2 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil)
    24. 3 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil),
    25. access([t2.c1], [t2.c2], [t2.c3]), partitions(p0)

    上述示例中,执行计划展示中 2 号算子 MATERIAL 的功能是保存 t2 表的数据,以避免每次联接都从磁盘扫描 t2 表的数据。执行计划展示中的 outputs & filters 详细展示了 MATERIAL 算子的输出信息如下:

    信息名称

    含义

    output

    该算子输出的表达式。

    其中 rownum() 表示 ROWNUM 对应的表达式。

    filter

    该算子上的过滤条件。

    由于示例中 MATERIAL 算子没有设置 filter,所以为 nil。