[TOC] # 实时执行计划展示 使用 EXPLAIN 命令可以展示出当前优化器所生成的执行计划,但由于统计信息变化、用户 session 变量设置变化等,会造成该 SQL 在计划缓存中实际对应的计划可能与 EXPLAIN 的结果并不相同。为了确定该 SQL 在系统中实际使用的执行计划,需要进一步分析计划缓存中的物理执行计划。 用户可以通过查询`(g)v$plan_cache_plan_explain`视图来展示某条 SQL 在计划缓存中的执行计划。 如下例所示: ~~~ obclient>VIEW_DEFINITION='SELECT * FROM oceanbase.gv$plan_cache_plan_explain WHERE IP =host_ip() AND PORT = rpc_port()' ~~~ 参数解释如下表: <table data-tag="table" id="table-ng3-qua-nd0" class="table"><colgroup span="1" width="240" data-tag="col" id="col-a8z-jaw-4dg" colwidth="1*" colnum="1" colname="col1" style="width:33.33333333333333%" class="col"></colgroup><colgroup span="1" width="240" data-tag="col" id="col-1a2-43o-69y" colwidth="1*" colnum="2" colname="col2" style="width:33.33333333333333%" class="col"></colgroup><colgroup span="1" width="240" data-tag="col" id="col-2r9-mzz-j2n" colwidth="1*" colnum="3" colname="col3" style="width:33.33333333333333%" class="col"></colgroup><thead id="thead-ww7-m4m-l7j" class="thead"><tr id="tr-jij-vc5-uw8"><th id="td-7fo-nap-ep2"><p id="p-1ht-mhz-9mm"><b>字段名称</b></p></th><th id="td-fu3-kbj-pbj"><p id="p-tye-hvj-eyz"><b>类型</b></p></th><th id="td-7vk-j8j-ptm"><p id="p-6i3-dm7-9d0"><b>描述</b></p></th></tr></thead><tbody data-tag="tbody" id="tbody-r15-nfn-iks" class="tbody"><tr data-tag="tr" id="tr-0p3-cf3-rs9" class="tr"><td data-tag="td" id="td-6sb-3p3-rbv" class="td"><p id="p-db1-jus-hlc">TENANT_ID</p></td><td data-tag="td" id="td-fj2-5z8-mcs" class="td"><p id="p-807-s37-uta">bigint(20)</p></td><td data-tag="td" id="td-ybz-8xr-7by" class="td"><p id="p-et7-g7v-370">租户 ID</p></td></tr><tr data-tag="tr" id="tr-xw6-w6j-j27" class="tr"><td data-tag="td" id="td-but-rqz-c20" class="td"><p id="p-vqq-c5i-7z2">IP</p></td><td data-tag="td" id="td-n8r-zkc-76h" class="td"><p id="p-o8t-8sz-6mj">varchar(32)</p></td><td data-tag="td" id="td-hm9-2el-t49" class="td"><p id="p-051-kvi-hhq">IP 地址</p></td></tr><tr data-tag="tr" id="tr-txt-ukg-wtr" class="tr"><td data-tag="td" id="td-usx-b46-8gi" class="td"><p id="p-0u2-wb9-2ae">PORT</p></td><td data-tag="td" id="td-qr3-ksr-ogj" class="td"><p id="p-d8c-647-tsq">bigint(20)</p></td><td data-tag="td" id="td-v6c-q4a-0ae" class="td"><p id="p-y16-340-1l6">端口号</p></td></tr><tr data-tag="tr" id="tr-tap-6c4-8ts" class="tr"><td data-tag="td" id="td-d90-jxb-vrv" class="td"><p id="p-o0f-ctl-kvw">PLAN_ID</p></td><td data-tag="td" id="td-jc9-0b2-343" class="td"><p id="p-wc5-1t3-eg7">bigint(20)</p></td><td data-tag="td" id="td-dw7-c8z-50t" class="td"><p id="p-80r-xrs-s0t">执行计划的 ID</p></td></tr><tr data-tag="tr" id="tr-xye-qy2-5kn" class="tr"><td data-tag="td" id="td-p8e-jym-qx4" class="td"><p id="p-8eu-7zp-if4">OPERATOR</p></td><td data-tag="td" id="td-ja2-iw3-k95" class="td"><p id="p-z1n-el3-tdi">varchar(128)</p></td><td data-tag="td" id="td-hdv-945-76e" class="td"><p id="p-j1b-wse-kuz">operator 的名称</p></td></tr><tr data-tag="tr" id="tr-f3o-4w4-j3n" class="tr"><td data-tag="td" id="td-yoa-yh0-auv" class="td"><p id="p-bcb-zlp-2br">NAME</p></td><td data-tag="td" id="td-0wp-de3-17q" class="td"><p id="p-ir5-jns-9gn">varchar(128)</p></td><td data-tag="td" id="td-lvc-llr-zgl" class="td"><p id="p-afa-zcw-vne">表的名称</p></td></tr><tr data-tag="tr" id="tr-mh1-mnh-ajn" class="tr"><td data-tag="td" id="td-iav-yi5-we1" class="td"><p id="p-v1e-574-za6">ROWS</p></td><td data-tag="td" id="td-mh9-t1r-2tf" class="td"><p id="p-0hv-99l-ksj">bigint(20)</p></td><td data-tag="td" id="td-ho1-3hx-oac" class="td"><p id="p-i7p-h6t-ipx">预估的结果行数</p></td></tr><tr data-tag="tr" id="tr-72g-i4o-e0s" class="tr"><td data-tag="td" id="td-fhj-jbb-06w" class="td"><p id="p-gbz-ln7-qo6">COST</p></td><td data-tag="td" id="td-2pu-dfx-hih" class="td"><p id="p-a27-u6s-ru9">bigint(20)</p></td><td data-tag="td" id="td-hmy-ipk-bx2" class="td"><p id="p-efk-8gl-t0e">预估的代价</p></td></tr><tr data-tag="tr" id="tr-wkg-n9z-vj4" class="tr"><td data-tag="td" id="td-4iw-5sa-1cl" class="td"><p id="p-rck-t0q-8g8">PROPERTY</p></td><td data-tag="td" id="td-lbm-54w-lc8" class="td"><p id="p-r8q-d1n-ov5">varchar(256)</p></td><td data-tag="td" id="td-9v2-9ys-1fg" class="td"><p id="p-9ao-jr8-1i3">对应 operator 的信息</p></td></tr></tbody></table> ## 第一步 查询 SQL 在计划缓存中的 plan\_id OceanBase 数据库每个服务器的计划缓存都是独立的。用户可以直接访问`v$plan_cache_plan_stat`视图查询本服务器上的计划缓存并提供 tenant\_id 和需要查询的 SQL 字符串(可以使用模糊匹配),查询该条 SQL 在计划缓存中对应的 plan\_id。 ~~~ 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 所展示的逻辑执行计划有所不同。 ~~~ 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 的值,否则系统将返回空集。