2015-04-28 22 views
5

miałem problem wydajności spowodowanych niewłaściwym XPath („@” brakuje atrybutu orzecznika) w zapytaniu jak ten:Zrozumienie wyjaśnić planu przez XMLType

wybierz extractvalue (pole „// item [attr =” wartość "]") z tabeli, gdzie pole1 =: 1;

Spodziewałem się wyjątku, ale wydaje mi się, że Oracle akceptuje tę konkretną ścieżkę x, ma znaczenie?

Próbowałem wykonać plan wyjaśniający w odniesieniu do tego zapytania, ale wynik jest dość dziwny, ktoś może mi pomóc go zrozumieć?

kiedyś tego kodu do odtworzenia ŚRODOWISKO

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 | 
------------------------------------------------------------------------------------------------ 
*/ 

W pierwszym wyjaśnienia nie jest „zagnieżdżony pętli” (wiersz 2) liczności 667K, które zniknęło na drugim. Umieszczenie większej liczby rekordów w tej samej tabeli i wykonanie nowego równania wyjaśniającego (bez "@"), która ma zawsze wartość 667K.

Co oznacza ta wartość?

Odpowiedz

1

Spodziewałem się wyjątku, ale wydaje mi się, że Oracle akceptuje tę konkretną ścieżkę, ma znaczenie?

Cóż, tak. Sam w sobie, xpath /root/g[key="G"] pobiera węzeł, który ma element potomny ze znacznikiem "klucz" i wartością "G". Tak więc, mimo że extractvalue zawiedzie (więcej niż jeden węzeł jest zwracany), to będzie działać:

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; 

Zwraca <g key="G"><key>G</key>Ggg</g>

Wysoki koszt może być uzasadnione w tego rodzaju poszukiwań, ponieważ atrybut prawdopodobnie bardziej zoptymalizowany i możliwy do wyszukania niż inne rodzaje pod-węzłów (wystarczy powiedzieć, że może istnieć tylko jedna z konkretną nazwą dla każdego znacznika, podczas gdy znaczniki mogą być powtarzane wiele razy).

Powiązane problemy