プライマリ・コンテンツに移動
Oracle® XML DB開発者ガイド
12cリリース1 (12.1)
B71282-04
目次へ移動
目次
索引へ移動
索引

前
次

19 オブジェクト・リレーショナル記憶域のXPathリライト

オブジェクト・リレーショナル形式で格納されたXMLTypeデータの場合、様々なSQL関数のXPath式引数に関する問合せは、基礎となるSQL表に対する問合せに自動的にリライトされることによって、高度に最適化されます。

19.1 オブジェクト・リレーショナル記憶域のXPathリライトの概要

Oracle XML DBでは、XPath式を使用する問合せ(たとえば、XPath (XQuery)式を引数として取るXMLQueryXMLTableXMLExistsなどのSQL関数を使用する問合せ)を最適化できることがよくあります。XPath式はXML文書に対して評価されますが、このときメモリー内でそのXML文書が構成されることはありません。

この最適化をXPathリライトと呼びます。これはXML問合せの最適化の適切なサブセットで、XPath式でないXQuery式(FLWOR式など)の最適化も行われます。また列に索引が存在する場合、XPathリライトによって、オプティマイザによる問合せの評価にその索引を使用できるようになります。

Oracle XML DBによってリライトできるXPath式は、Oracle XML DBでサポートされているXPath式の適切なサブセットです。機能性を損わずにXPath式をリライトできる場合は、リライト可能なXPath式を使用してください。

XPathリライトは、次のような状況(またはこれらの状況の組合せ)で可能です。

ここでは、第1のケースである、オブジェクト・リレーショナルXMLデータまたはXMLTypeビューを使用する問合せのリライトについて説明します。XMLTypeビューは、XML Schemaに基づくビューでも、XML Schemaに基づかないビューでもかまいません。XMLTypeデータのオブジェクト・リレーショナル記憶域は常に、XML Schemaに基づいています。この章の例は、XML Schemaに基づく表に関するものです。

オブジェクト・リレーショナルXMLデータでXPathリライトが可能な場合、データベース・オプティマイザは従来の関係代数に基づいて実行計画を導出できます。これはまた、Oracle XML DBが、データベースのすべての機能を使用でき、XQuery式やXPath式を含むSQL文がパフォーマンスの高い効率的な方法で実行されることが保証されることを意味します。このリライトによるオーバーヘッドはほとんどないため、Oracle XML DBは、リレーショナルSQL文とほぼ同じ速度でXQueryベースおよびXPathベースの問合せを実行できます。

XPathリライトを実行できない場合もあります。これは、通常、XPath式に対して同等のSQLがない場合に発生します。この場合、Oracle XML DBはXPath式の機能評価を実行し、一般に、処理する文書数が多い場合は特に、コストが増加します。

例19-1は、XPath式を使用する単純な問合せのXPathリライトを示しています。

例19-1 XPathリライト

SELECT po.OBJECT_VALUE FROM purchaseorder po
  WHERE XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
                         PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
                AS VARCHAR2(128))
        = 'Sarah J. Bell';

XMLCast(XMLQuery...))式は、発注書の要求者情報が格納される、基礎となるリレーショナル列にリライトされます。この問合せは次のようにリライトされます。脚注1

SELECT OBJECT_VALUE FROM purchaseorder p
 WHERE CAST (p."XMLDATA"."REQUESTOR" AS VARCHAR2(128)) = 'Sarah J. Bell';

19.2 リライトされる一般的なXPath式

XPathリライト中にリライトされる最も一般的なXPath式について説明します。

表19-1に説明を示します。

表19-1 基礎となるSQL構造体にリライトされるXPath式のサンプル

変換されるXPath式 説明

単純なXPath式(childおよびattribute軸のみを持つ式):

/PurchaseOrder/@Reference

/PurchaseOrder/Requestor

属性自体が単純なスカラー型またはオブジェクト型である場合、オブジェクト型の属性のみに対して全検索が行われます。

コレクション全検索式:

/PurchaseOrder/LineItems/LineItem/Part/@Id

コレクション式の全検索が行われます。サポートされる軸は、child軸およびattribute軸のみです。CREATE INDEX操作の間にSQL関数が使用される場合、コレクションの全検索はサポートされません。

述語:

[Requestor = "Sarah J. Bell"]

XPathの述語は、SQL述語にリライトされます。

リスト索引(位置指定述語):

LineItem[1]

コレクションのn番目の項目にアクセスするように索引がリライトされます。

ワイルド・カード全検索:

/PurchaseOrder/*/Part/@Id

ワイルドカードを1つ以上の単純なXPath式に変換できる場合は、リライトされます。

descendant軸(XML Schemaに基づくデータのみ)、再帰なし:

/PurchaseOrder//Part/@Id

ワイルド・カード式と同様です。descendant軸は、1つ以上の単純なXPath式にマップできる場合にリライトされます。

descendant軸(XML Schemaに基づくデータのみ)、再帰あり:

/PurchaseOrder//Part/@Id

両方の条件を満たす場合、descendant軸はリライトされます。

  • このXPath式が展開される単純なXPath式は、すべて同じ表外の表にマップされます。

  • このXPath式が展開されない単純なXPath式はすべて、その表外の表にはマップされません。

XPath関数

一部のXPath関数がリライトされます。これらの関数には、notfloorceilingsubstringおよびstring-lengthがあります。

関連項目:

XQuery式のリライトの詳細は、「XQuery用のパフォーマンス・チューニング」を参照してください。

19.3 表外の表に対するXPathリライト

表外に格納されている要素を含むXPath式は自動的にリライトできます。リライトされた問合せでは、表外の表との結合が行われます。

例19-2に、このような問合せを示します。XQuery式はSQL EXISTS副問合せにリライトされています。これは表addr_tabを問い合せ、表addr_tab内のオブジェクト識別子列を使用して表emp_tabと結合します。オプティマイザは表emp_tabおよびaddr_tabの全表スキャンを使用します。addr_tabに多数のエントリがある場合、例19-3に示すように、cityに索引を作成することで、この問合せの効率を高めることができます。例19-2と同じ問合せの実行計画の断片は、cityの索引が取得されることを示しています。

注意:

オブジェクト・リレーショナルに格納されているXMLType表でオプティマイザの統計を収集する場合、XML Schemaで定義されたすべての表、つまりUSER_XML_TABLES内のすべての表で統計を収集することをお薦めします。そのためには、プロシージャDBMS_STATS.gather_schema_statsを使用するか、対象の各表に対してDBMS_STATS.gather_table_statsを使用します。これによりオプティマイザは、XMLTypeデータを格納するために使用されているすべての依存表について情報を取得できます。

例19-2 表外の表のXPathリライト

SELECT XMLCast(XMLQuery('declare namespace x = "http://www.oracle.com/emp.xsd"; (: :)
                         /x:Employee/Name' PASSING OBJECT_VALUE RETURNING CONTENT)
               AS VARCHAR2(20))
  FROM emp_tab
  WHERE XMLExists('declare namespace x = "http://www.oracle.com/emp.xsd"; (: :)
                   /x:Employee/Addr[City="San Francisco"]' PASSING OBJECT_VALUE);

XMLCAST(XMLQUERY(...
--------------------
Abe Bee
Eve Fong
George Hu
Iris Jones
Karl Luomo
Marina Namur
Omar Pinano
Quincy Roberts
 
8 rows selected.

例19-3 表外の表での索引の使用

CREATE INDEX addr_city_idx
  ON addr_tab (extractValue(OBJECT_VALUE, '/Addr/City'));
|   2 |   TABLE ACCESS BY INDEX ROWID| ADDR_TAB      |     1 |  2012 |     1   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | ADDR_CITY_IDX |     1 |       |     1   (0)| 00:00:01 |
|   4 |   TABLE ACCESS FULL          | EMP_TAB       |    16 | 32464 |     2   (0)| 00:00:01 |

19.4 XPath問合せを解析および最適化する実行計画を使用する場合のガイドライン

実行計画を使用して、問合せの実行を分析して、(a) XPathリライトが発生したかどうかを確認し、(b) 2次索引を使用して問合せの実行を最適化するガイドラインを示します。これらのガイドラインは、オブジェクト・リレーショナル形式で格納されるXMLTypeデータにのみ適用されます。

これらのガイドラインを一緒に使用し、適用されるすべての事項を考慮します。

オブジェクト・リレーショナル記憶域のXPathリライトとは、XPath式で定義されるXMLフラグメントを選択する問合せが、基礎となるオブジェクト・リレーショナル表および列のSQL SELECT文にリライトされることです。基礎となるこれらの表には、表外の表を含めることができます。

PL/SQLプロシージャDBMS_XMLSTORAGE_MANAGE.XPath2TabColMappingを使用すると、指定されたXPath式に対応する基礎となる表および列の名前を検索できます。

関連項目:

19.4.1 ガイドライン: 実行計画内のXML関数に対する基礎となる表の検索

リライトされた問合せの実行計画は、問合せ対象のXMLTypeデータの基礎となるオブジェクト・リレーショナル表および列の名前を参照します。これらの名前は、XML要素または属性名から導出された場合、またはXML Schema注釈xdb:defaultTableが使用された場合に、意味を持つ場合があります。

そうでない場合、名前はシステムにより生成され、明確な意味を持ちません。これらの名前には、対応するXML要素または属性の名前はを反映されません。

また、システム生成の列の一部は、通常は非表示です。SQL describeコマンドを使用すると、それらは表示できません。その場合でも実行計画には表示されます。

リライトされていない問合せの計画には、実表の名前のみが表示され、通常は、XMLExistsなどのユーザー・レベルXML関数を参照します。問合せが最適化されているかどうかを判断するには、この違いを調べてください。実行計画に表示されるXML関数名は、実際には内部名(XMLEXISTS2など)で、ユーザー・レベルの名前と多少異なることがあります。

例19-4に、Oracle XML DBがXPathリライトを実行できない場合に生成される実行計画の出力の種類を示します。ここでの計画はSQL/XML関数XMLExistsを使用する問合せに対するものです。計画の出力に、対応する内部関数XMLExists2があり、これは問合せがリライトされないことを示します。

この場合、Oracle XML DBは、問合せのWHERE句で指定した他の条件に基いて、事前フィルタされた結果セットを構成します。次に、この潜在的な結果セットの行をフィルタして、結果セットに属する行を決定します。フィルタリングでは、各文書でDOMが構築され、DOM APIにより定義されたメソッドを使用して機能評価が実行され、各文書が結果セットのメンバーかどうかが判断されます。

例19-4 XPathリライトを実行しない場合に生成される実行計画

Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(XMLEXISTS2('$p/PurchaseOrder[User="SBELL"]' PASSING BY VALUE
              SYS_MAKEXML('61687B202644E297E040578C8A175C1D',4215,"PO"."XMLEXTRA","PO"."X
              MLDATA") AS "p")=1)

19.4.2 ガイドライン: 実行計画で認識するためのオブジェクト・リレーショナル表の名前付け

XML Schemaを設計する場合は、注釈xdb:defaultTableを使用して、基礎となる表に名前を付けます。この表はパフォーマンスが重要な問合せで選択する要素に対応します。これにより、実行計画でそれらを容易に識別できるようになり、問合せがリライトされたかどうかがわかります。

コレクション表には、対応するXML Schema注釈がありません。コレクション表にわかりやすい名前を付けるには、最初にXML Schemaを登録する必要があります。その後で、PL/SQLプロシージャDBMS_XMLSTORAGE_MANAGE.renameCollectionTableを使用すると、登録時に作成された表の名前(システムで生成された名前)を変更できます。

関連項目:

プロシージャrenameCollectionTableの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

19.4.3 ガイドライン: 述語でターゲットとなっている列に対する索引の作成

SQL述語のターゲットとなる列に適用される索引を作成して、そのSQL述語を含むようにリライトされる問合せのパフォーマンスを向上できる場合があります。

XPathリライトから生成された問合せには、SQL述語(WHERE句)が含まれる場合があります。これは、元の問合せでXPath述語が使用されない場合や、元の問合せにSQL WHERE句がない場合でも発生することがあります。

この場合は、SQL述語のターゲットとなる列に対して索引を作成したり、その列の関数適用に対して索引を作成することで、パフォーマンスを向上できる場合があります。

例19-1は、WHERE句を含む問合せのXPathリライトを示しています。例19-5は、この問合せの実行計画からの述語情報を示しています。

述語情報では、発注書SYS_NC0021$の要求者情報が格納される、基礎となるリレーショナル列のSQL関数castの使用に合せて、XMLCast(XMLQuery...))式がリライトされることを示します。この列名はシステム生成されます。適用されるXML Schemaでは、注釈SQLNameを使用してこの列REQUESTORに名前を付けますが、実行計画では、システム生成されたこの名前を参照します。

これらの2つの名前(ユーザー定義およびシステム生成)は同じ列を参照するため、いずれかの名前を使用して、この列に対してBツリー索引を作成できます。また、extractValueショートカットを使用し、発注書の要求者データをターゲットとするXPath式を指定することで索引を作成することもできます。

プロシージャDBMS_XMLSTORAGE_MANAGE.XPath2TabColMappingを使用すると、指定されたXPath式に対応する基礎となる表および列の名前を取得できます。例19-6は、例19-1WHERE句で使用されているXPath式/PurchaseOrder/Requestorで、これを説明しています。

ワイルドカードまたは子孫軸を含むXPath式を指定する場合、複数の表および列が選択されます。その場合、プロシージャXPath2TabColMappingでは、複数の<Mapping>要素(表と列のペアごとに1つずつ)を戻します。

その後、この方法で取得した表名および列名をCREATE INDEX文で使用すれば、XPath式に対応する索引を作成できます。例19-7は、述語でターゲットとなっている列に対してBツリー索引を作成する3つの同等の方法を示しています。

ただし、この問合せでは、リライトされた問合せの式に一致するファンクション式を使用してファンクション索引を作成することをお薦めします。例19-8に、これを示します。

例19-9は、索引が取り出されることを示す実行計画を示しています。

この問合せの場合では、元のファンクション式によってXMLCastXMLQueryに適用され、単一要素のRequestorがターゲットになります。これは、CREATE INDEX文でこうしたファンクション式をショートカットとして直接使用できる特殊なケースです。基礎となるスカラー・データ上に索引を作成するように、その文がリライトされます。例19-10はXPath式をターゲットとしており、対応するオブジェクト・リレーショナル列をターゲットとする例19-8と同じ結果になります。

関連項目:

  • XMLQueryに適用されるXMLCastのショートカットおよび単一のデータに索引付けするためのextractValueショートカットの使用方法の詳細は、「繰り返し使用しないテキスト・ノードまたは属性値の索引付け」を参照してください

  • プロシージャXPath2TabColMappingの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

例19-5 実行計画の分析による列と索引の対応の特定

Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(CAST("PURCHASEORDER"."SYS_NC00021$" AS VARCHAR2(128))='Sarah
              J. Bell' AND SYS_CHECKACL("ACLOID","OWNERID",xmltype('<privilege
              xmlns="http://xmlns.oracle.com/xdb/acl.xsd"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.oracle.com/xdb/acl.xsd
              http://xmlns.oracle.com/xdb/acl.xsd DAV:http://xmlns.oracle.com/xdb/dav.xsd
              "><read-properties/><read-contents/></privilege>'))=1)

例19-6 DBMS_XMLSTORAGE_MANAGE.XPATH2TABCOLMAPPINGの使用

SELECT DBMS_XMLSTORAGE_MANAGE.XPath2TabColMapping(USER,
                                                  'PURCHASEORDER',
                                                  '',
                                                  '/PurchaseOrder/Requestor',
                                                  '')
  FROM  DUAL;

DBMS_XMLSTORAGE_MANAGE.XPath2TabColMapping(US
---------------------------------------------
<Result>
  <Mapping TableName="PURCHASEORDER" ColumnName="SYS_NC00021$"/>
</Result>

例19-7 述語でターゲットとなっている列に対する索引の作成

CREATE INDEX requestor_index ON purchaseorder ("SYS_NC00021$");

CREATE INDEX requestor_index ON purchaseorder ("XMLDATA"."REQUESTOR");

CREATE INDEX requestor_index ON purchaseorder
  (extractvalue(OBJECT_VALUE, '/PurchaseOrder/Requestor'));

例19-8 述語でターゲットとなっている列に対するファンクション索引の作成

CREATE INDEX requestor_index ON purchaseorder
  (cast("XMLDATA"."REQUESTOR" AS VARCHAR2(128)));

例19-9 索引が取得されていることを示す実行計画

-----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                 |     1 |   524 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| PURCHASEORDER   |     1 |   524 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | REQUESTOR_INDEX |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter(SYS_CHECKACL("ACLOID","OWNERID",xmltype('<privilege
              xmlns="http://xmlns.oracle.com/xdb/acl.xsd"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.oracle.com/xdb/acl.xsd
                                  http://xmlns.oracle.com/xdb/acl.xsd
              DAV:http://xmlns.oracle.com/xdb/dav.xsd">
              <read-properties/><read-contents/></privilege>'))=1)
   2 - access(CAST("SYS_NC00021$" AS VARCHAR2(128))='Sarah J. Bell')

例19-10 述語でターゲットとなっている列に対するファンクション索引の作成

CREATE INDEX requestor_index 
  ON purchaseorder po
     (XMLCast(XMLQuery('$p/PurchaseOrder/Requestor' PASSING po.OBJECT_VALUE AS "p"
                                                    RETURNING CONTENT)
              AS VARCHAR2(128)));

19.4.4 ガイドライン: Ordered Collection表に対する索引の作成

Ordered Collection Table (OCT)またはXMLTypeインスタンスとしてコレクションが格納されている場合は、コレクションのメンバーに直接アクセスできます。各メンバーは表の行になるため、SQLで直接アクセスできます。このようなコレクション・メンバーに索引付けすることによって、パフォーマンスを向上できます。

これを実行するには、コレクションXML要素またはその属性、および疑似NESTED_TABLE_IDに対応するオブジェクト属性に対して、コンポジット索引を作成します。

例19-11では、部品番号717951002372 (Id属性の値が717951002372Part要素)の発注を含む文書からReference要素を検索する問合せの実行計画を示します。LineItem要素のコレクションは、Ordered Collection Table、lineitem_tableに行として格納されています。

注意:

例19-11では、サンプル・データベース・スキーマOEpurchaseorder表を使用しません。これは、コレクション要素LineItemlineitem_tableという名前のOrdered Collection Table (OCT)を使用するpurchaseorder表を使用します。

実行計画は、Ordered Collection Table、lineitem_tableの全体スキャンを示しています。この計画は、purchaseorder表内の文書の数が数百しかなければ許容されますが、表内に数千または数百万の文書がある場合は許容されません。

このような問合せのパフォーマンスを改善するには、属性Idの値を指定した疑似列NESTED_TABLE_IDに直接アクセスできる索引を作成します。しかし、Oracle XML DBでは、XPath式を直接使用してコレクションに対する索引を作成することはできません。索引を作成するには、LineItem要素の管理に使用するSQLオブジェクトの構造を理解する必要があります。その情報に基づいて、従来のオブジェクト・リレーショナルSQLを使用して必要な索引を作成できます。

ここでは、要素LineItemはオブジェクト・タイプlineitem_tのインスタンスとして格納されています。また、要素PartはSQLデータ型part_tのインスタンスとして格納されています。XML属性Idは、オブジェクト属性part_numberにマップされています。これらの情報に基づいて、例19-12に示すように、属性part_numberおよび疑似列NESTED_TABLE_IDに対するコンポジット索引を作成できます。この索引によって、必要な部品を参照するLineItem要素が含まれた発注書に直接アクセスできます。

例19-11 コレクション要素の選択の実行計画

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(4000)) "Reference"
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part[@Id="717951002372"]'
                  PASSING OBJECT_VALUE AS "p");
-------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                        |    21 |  2352 |    20  (10)| 00:00:01 |
|*  1 |  HASH JOIN RIGHT SEMI        |                        |    21 |  2352 |    20  (10)| 00:00:01 |
|   2 |   JOIN FILTER CREATE         | :BF0000                |    22 |   880 |    14   (8)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL         | LINEITEM_TABLE         |    22 |   880 |    14   (8)| 00:00:01 |
|   4 |   JOIN FILTER USE            | :BF0000                |   132 |  9504 |     5   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS FULL         | PURCHASEORDER          |   132 |  9504 |     5   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("NESTED_TABLE_ID"="PURCHASEORDER"."SYS_NC0003400035$")
   3 - filter("SYS_NC00011$"='717951002372')
   5 - filter(SYS_OP_BLOOM_FILTER(:BF0000,"PURCHASEORDER","SYS_NC0003400035$"))

例19-12 Ordered Collection Tableに直接アクセスするための索引の作成

CREATE INDEX lineitem_part_index ON lineitem_table l (l.part.part_number, l.NESTED_TABLE_ID);

19.4.5 ガイドライン: XMLOptimizationCheckを使用した、問合せがリライトされない理由の特定

問合せが最適化されていない場合、システム変数XMLOptimizationCheckを使用して理由を特定できます。



脚注の凡例

脚注1:

この例では、サンプルのデータベース・スキーマOEとその表purchaseorderを使用しています。この表のXML Schemaには、REQUESTORなどのSQLオブジェクト属性名を指定するために、属性SQLNameで注釈が付けられています(例A-2を参照)。このような注釈を使用しないと、例では、p."XMLDATA".".REQUESTOR"ではなくp."XMLDATA"."Requestor"が使用されます。