实时执行计划展示 
=============================







使用 EXPLAIN 命令，可以展示出当前优化器所生成的执行计划，但该 SQL 在计划缓存中实际对应的计划可能与 EXPLAIN 的结果并不相同，造成这种现象的原因有很多，诸如统计信息变化、用户 session 变量设置变化等等。为了确定该 SQL 在系统中实际使用的执行计划，有时还需要进一步分析计划缓存中的物理执行计划。

用户可以通过查询 `(g)v$plan_cache_plan_explain` 虚拟表来展示某条 SQL 在计划缓存中的执行计划。

对于 plan cache 中 plan 的基本信息解释如下例所示：

```javascript
view_definition='SELECT * 
FROM oceanbase.gv$plan_cache_plan_explain
WHERE IP =HOST_IP() AND PORT = RPC_PORT()'
```



字段定义如下表：


| **字段名称**  |    **类型**    |     **描述**      |
|-----------|--------------|-----------------|
| TENANT_ID | bigint(20)   | 租户 ID           |
| IP        | varchar(32)  | IP 地址           |
| PORT      | bigint(20)   | 端口号             |
| PLAN_ID   | bigint(20)   | 执行计划的 ID        |
| OPERATOR  | varchar(128) | operator 的名称    |
| NAME      | varchar(128) | 表的名称            |
| ROWS      | bigint(20)   | 预估的结果行数         |
| COST      | bigint(20)   | 预估的代价           |
| PROPERTY  | varchar(256) | 对应 operator 的信息 |





第一步 查询 SQL 在计划缓存中的 plan_id 
-----------------------------------

OceanBase 数据库的计划缓存是每个服务器一个计划缓存。查询本服务器上的计划缓存，用户可以直接访问 `v$plan_cache_plan_stat` 视图，并提供租户 ID 和需要查询的 SQL 字符串（可以使用模糊匹配），查询该条 SQL 在计划缓存中对应的 `plan_id`。

```javascript
obclient>select * 
                          from v$plan_cache_plan_stat 
                          where tenant_id= 1001 
                                and statement like 'insert into t1 values%'\G
***************************1. row ***************************
       tenant_id: 1001
          svr_ip:100.81.152.44
        svr_port:15212
         plan_id: 7
          sql_id:0
            type: 1
       statement: insert into t1 values(1)
       plan_hash:1
last_active_time:2016-05-28 19:08:57.416670
    avg_exe_usec:0
slowest_exe_time:1970-01-01 08:00:00.000000
slowest_exe_usec:0
      slow_count:0
       hit_count:0
        mem_used:8192
1 rowin set (0.01 sec)
```





第二步 使用得到的 plan_id 展示对应执行计划 
-----------------------------------

获得 `plan_id` 后，用户可以使用 `tenant_id` 和 `plan_id` 访问 `v$plan_cache_plan_explain` 来展示在该执行计划。
**注意**



这里展示的计划为物理执行计划，在算子命名上会与 EXPLAIN 所展示的逻辑执行计划有所不同。

```javascript
obclient> select * 
                            from v$plan_cache_plan_explain
                            where tenant_id = 1001 and plan_id = 7;
+-----------+---------------+-------+---------+--------------------+------+------+------+
| TENANT_ID | IP            | PORT  | PLAN_ID | OPERATOR           | NAME | ROWS | COST |
+-----------+---------------+-------+---------+--------------------+------+------+------+
|      1001 | 100.81.152.44 | 15212 |       7 |  PHY_ROOT_TRANSMIT | NULL |    0 |    0 |
|      1001 | 100.81.152.44 | 15212 |       7 |   PHY_INSERT       | NULL |    0 |    0 |
|      1001 | 100.81.152.44 | 15212 |       7 |    PHY_EXPR_VALUES | NULL |    0 |    0 |
+-----------+---------------+-------+---------+--------------------+------+------+------+
3 rows in set (0.01 sec)
```


**注意**



* 如果访问 `gv$plan_cache_plan_explain`，必须给定 `ip`，`port`，`tenant_id` 和 `plan_id` 这四列的值；

  

* 如果访问 `v$plan_cache_plan_explain`，必须给定 `tenant_id` 和 `plan_id` 的值，否则，系统将返回空集。

  



