MATERIAL 
=============================

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

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

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

```javascript
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   | 该算子输出的表达式。 其中 r`ownum()` 表示 `ROWNUM` 对应的表达式。           |
| filter   | 该算子上的过滤条件。 由于示例中 `MATERIAL` 算子没有设置 `filter`，所以为 `nil`。 |


