ヘッダーをスキップ
Oracle® XML DB開発者ガイド
11gリリース2 (11.2)
B70200-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

8 構造化記憶域のXPathリライト

この章では、Oracle XML DBの構造化(オブジェクト・リレーショナル)記憶域のXPathリライトの基礎について説明します。様々なSQL関数のXPath式引数のリライトについて詳しく説明します。

この章の内容は次のとおりです。

構造化記憶域のXPathリライトの概要

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

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

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

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

  • XMLTypeデータがオブジェクト・リレーショナル形式の列または表(構造化記憶域)に格納されている場合、またはリレーショナル・データに基づいてXMLTypeビューが構築されている場合。

  • XMLIndex索引を使用する場合。「XMLIndex」を参照してください。

  • XMLTypeデータがバイナリXMLとして格納されている場合。ストリーミング評価の詳細は、「Oracle XML DBでのXMLTypeメソッドおよびSQL関数の処理」を参照してください。

この章では、第1のケースである、構造化XMLデータまたはXMLTypeビューを使用する問合せのリライトについて説明します。XMLTypeビューは、XML Schemaに基づくビューでも、XML Schemaに基づかないビューでもかまいません。XMLTypeデータの構造化記憶域は常に、XML Schemaに基づいています。この章の例は、XML Schemaに基づく表に関するものです。

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

例8-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';

リライトされるXPath式のサンプル

表8-1は、XPathリライトでリライトされるいくつかのXPath式を示しています。

表8-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用のパフォーマンス・チューニング」を参照してください。

実行計画を使用したXPath問合せの分析および最適化

この項では、XPath式を使用する問合せで、次の操作を実行するための実行計画を使用する場合のガイドラインについて説明します。

  • 問合せ計画の分析による、XPathリライトが行われるかどうかの判断。

  • 2次索引を使用した問合せ実行の最適化。

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

この章の残りの部分にも当てはまりますが、この項は、オブジェクト・リレーショナル形式(構造化記憶域)で格納されるXMLTypeデータのみに適用されます。

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

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

リライトされた問合せの実行計画は、問合せ対象のXMLTypeデータの基礎となるオブジェクト・リレーショナル表および列を参照します。

基礎となる表の名前は、XML要素または属性名から導出された場合、または適用されるXML Schemaによりxdb:defaultTable注釈を使用して明示的に名前が付けられる場合に、意味を持つ場合があります。そうでない場合、名前はシステムにより生成され、明確な意味を持ちません。これらの名前には、対応するXML要素または属性の名前はを反映されません。また、システム生成の列の一部は非表示です。SQL describeコマンドを使用すると、それらは表示できません。その場合でも実行計画には表示されます。

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

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

例8-2 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)

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

ガイドライン: 実行計画で認識するためのデフォルト表の名前付け

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

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

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

この場合は、SQL述語のターゲットとなる列に対して索引を作成したり、その列の関数適用に対して索引を作成することで、パフォーマンスを向上できる場合があります。例8-1は、WHERE句を含む問合せのXPathリライトを示しています。例8-3は、この問合せの実行計画からの述語情報を示しています。

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

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)

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

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

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

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'));

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

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

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

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

例8-6 索引が選択されていることを示す実行計画

-----------------------------------------------------------------------------------------------
| 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')

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

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

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

関連項目:

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

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

Ordered Collection TableまたはXMLTypeインスタンスとしてコレクションが格納されている場合は、コレクションのメンバーに直接アクセスできます。コレクションの各メンバーは表内の行になるため、SQLで直接アクセスできます。

このようなコレクション・メンバーに索引付けすることによって、パフォーマンスを向上できます。これを実行するには、コレクションXML要素またはその属性、および疑似NESTED_TABLE_IDに対応するオブジェクト属性に対して、コンポジット索引を作成します。

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


注意:

例8-8では、サンプル・データベース・スキーマOEpurchaseorder表を使用しません。例3-13で定義したpurchaseorder表を使用します。この表はコレクション要素LineItem用のlineitem_tableという名前のOrdered Collection Table (OCT)を使用します。

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

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             |                        |     1 |   122 |    16  (13)| 00:00:01 |
|   1 |  NESTED LOOPS                |                        |       |       |            |          |
|   2 |   NESTED LOOPS               |                        |     1 |   122 |    16  (13)| 00:00:01 |
|   3 |    SORT UNIQUE               |                        |     1 |    50 |    14   (8)| 00:00:01 |
|*  4 |     TABLE ACCESS FULL        | LINEITEM_TABLE         |     1 |    50 |    14   (8)| 00:00:01 |
|*  5 |    INDEX UNIQUE SCAN         | LINEITEM_TABLE_MEMBERS |     1 |       |     0   (0)| 00:00:01 |
|   6 |   TABLE ACCESS BY INDEX ROWID| PURCHASEORDER          |     1 |    72 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - filter("SYS_NC00009$" IS NOT NULL AND "SYS_NC00011$"='717951002372')
   5 - access("NESTED_TABLE_ID"="PURCHASEORDER"."SYS_NC0003400035$")

実行計画は、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にマップされています。これらの情報に基づいて、例8-9に示すように、属性part_numberおよび疑似列NESTED_TABLE_IDに対するコンポジット索引を作成できます。この索引によって、必要な部品を参照するLineItem要素が含まれた発注書に直接アクセスできます。

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

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

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

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



脚注の凡例

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