Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 通过xmltype理解解释计划_Oracle_Xpath_Xmltype_Sql Execution Plan - Fatal编程技术网

Oracle 通过xmltype理解解释计划

Oracle 通过xmltype理解解释计划,oracle,xpath,xmltype,sql-execution-plan,Oracle,Xpath,Xmltype,Sql Execution Plan,我遇到了一个性能问题,原因是在如下查询的属性谓词中缺少错误的xpath“@”: 从field1=:1的表中选择extractvaluefield,//item[attr=value] 我预计会出现异常,但Oracle似乎接受这个特定的xpath, 有意义吗 我试图对该查询执行解释计划,但结果非常奇怪,有人能帮我理解吗 我使用此代码来重现环境 SELECT * FROM V$VERSION; /* Oracle Database 11g Release 11.2.0.3.0 - 64bit Pro

我遇到了一个性能问题,原因是在如下查询的属性谓词中缺少错误的xpath“@”:

从field1=:1的表中选择extractvaluefield,//item[attr=value]

我预计会出现异常,但Oracle似乎接受这个特定的xpath, 有意义吗

我试图对该查询执行解释计划,但结果非常奇怪,有人能帮我理解吗

我使用此代码来重现环境

SELECT * FROM V$VERSION;
/*
Oracle Database 11g Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
"CORE   11.2.0.3.0  Production"
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
*/

create table TMP_TEST_XML(
  id number,
 content_xml xmltype 
);
/
create unique index IDX_TMP_TEST_XML on TMP_TEST_XML(id);
/
declare
  xml xmltype := xmltype('<root>
    <a key="A">Aaa</a>
    <b key="B">Bbb</b>
    <c key="C">Ccc</c>
    <d key="D">Ddd</d>
    <e key="E">Eee</e>
    <f key="F">Fff</f>
    <g key="G">Ggg</g>
    <h key="H">Hhh</h>
    <i key="I">Iii</i>
    <l key="L">Lll</l>
</root>');
begin

  for idx in 1..10000 
  loop
    insert into TMP_TEST_XML values (idx, xml);
  end loop;

  commit;

end;
/
--explain plan xpath without '@' (wrong)
EXPLAIN PLAN SET statement_id = 'planXml1' FOR
select extractvalue(content_xml, '/root/g[key="G"]') from TMP_TEST_XML where id between 120 and 130;
/    
select plan_table_output
from table(dbms_xplan.display('plan_table',null,'advanced'));
/
/*
------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                  |    24 | 48360 |     4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE             |                  |     1 |     4 |            |          |
|   2 |   NESTED LOOPS SEMI         |                  |   667K|  2606K|   223K  (1)| 00:44:37 |
|   3 |    XPATH EVALUATION         |                  |       |       |            |          |
|*  4 |    XPATH EVALUATION         |                  |       |       |            |          |
|   5 |  TABLE ACCESS BY INDEX ROWID| TMP_TEST_XML     |    24 | 48360 |     4   (0)| 00:00:01 |
|*  6 |   INDEX RANGE SCAN          | IDX_TMP_TEST_XML |    43 |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
*/
/
-- explain plan xpath with '@' (correct)
EXPLAIN PLAN SET statement_id = 'planXml1' FOR
select extractvalue(content_xml, '/root/g[@key="G"]') from TMP_TEST_XML where id between 120 and 130;
/
select plan_table_output
from table(dbms_xplan.display('plan_table',null,'advanced'));
/
/*
------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                  |    24 | 48360 |     4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE             |                  |     1 |     4 |            |          |
|*  2 |   XPATH EVALUATION          |                  |       |       |            |          |
|   3 |  TABLE ACCESS BY INDEX ROWID| TMP_TEST_XML     |    24 | 48360 |     4   (0)| 00:00:01 |
|*  4 |   INDEX RANGE SCAN          | IDX_TMP_TEST_XML |    43 |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
*/
在第一个解释中,有一个基数为667K的“嵌套循环”第2行在第二个解释中消失了。 在同一个表中插入更多记录,并在不带“@”的情况下执行新的解释平原,该值始终为667K

它代表了什么价值

我期待一个例外,但Oracle似乎接受这个特定的xpath,这有什么意义

嗯,是的。xpath/root/g[key=g]本身会获取具有标记key和值g的子节点的节点。因此,即使在返回多个节点时extractvalue会失败,这也会起作用:

select extract(xmltype('<root>
<a key="A">Aaa</a>
<g key="G"><key>G</key>Ggg</g>
<h key="H">Hhh</h></root>'),'/root/g[key="G"]').getStringVal() from dual;
它返回GGgg

这种搜索的高成本是合理的,因为与其他类型的子节点相比,属性可能更优化、更可搜索。可以说,每个标记只能有一个具有特定名称的子节点,而标记可以重复多次