この章では、Oracle XML DBでのXPathリライトの基礎、およびそれをXML Schemaに基づく構造化記憶域に対して使用する方法について説明します。SQL関数(existsNode、extract、extractValue、XMLSequence、updateXML、insertChildXMlおよびdeleteXML)のXPath式引数のリライトについて詳しく説明します。
この章の内容は次のとおりです。
オブジェクト・リレーショナル形式(構造化記憶域)で格納されているXML Schemaに基づくデータでは、XQuery式を使用してそのデータを問い合せると、多くの場合、問合せは基礎となるオブジェクト・リレーショナル列に直接リライトされます。このクエリー・リライトは、特定のXML Schemaに基づかないXMLTypeビューでXQuery式を使用して問合せを行った場合も発生します。XQuery式のリライトの最適化プロセスを、XPathリライトといいます。
この最適化によって、Bツリーまたは他の索引が列に存在する場合、これらをオプティマイザによる問合せの評価に使用できます。XPathリライトのメカニズムは、XMLQuery、XMLTable、XMLExists、existsNode、extract、extractValue、updateXMLなどのSQL関数へのXPath式引数に対して使用されます。これにより、メモリー内でXML文書を構成せずに、XPath式をXML文書に対して評価できます。
Oracle XML DBによってリライトされるXPath式は、Oracle XML DBでサポートされるXPath式の適切なサブセットです。機能性を損なわずにXPath式をリライトできる場合は、リライト可能なXPath式を使用してください。
例7-1 XPathリライト
たとえば、次のような問合せでは、Company要素の値の取得およびリテラル文字列Oracleとの比較が試行されます。
SELECT OBJECT_VALUE FROM mypurchaseorders WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') = 'Oracle';
表mypurchaseordersがXML Schemaに基づく構造化記憶域で作成されているとすると、extractValue式は、発注書についての企業情報を格納する基礎となるリレーショナル列にリライトされます。問合せは次のようにリライトされます。
SELECT VALUE(p) FROM mypurchaseorders p WHERE p.XMLDATA."Company" = 'Oracle';
Company列に対して次のような索引が作成されている場合、前述の問合せでは、問合せの評価にこの索引が使用されます。
CREATE INDEX company_index ON mypurchaseorders e (extractValue(OBJECT_VALUE, '/PurchaseOrder/Company'));
XPathリライトは、XML Schemaに基づく表、およびXML Schemaに基づくビューとXML Schemaに基づかないビューに対して発生します。この章では、XML Schemaに基づく表に関する例のみを考えます。
例7-2のSQL関数updateXMLのXPath引数は、同等のオブジェクト・リレーショナルなSQL文例7-3にリライトされます。
例7-2 UPDATEXMLでのXPathリライト
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User')
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
EXTRACTVAL
----------
SBELL
1 row selected.
UPDATE purchaseorder
SET OBJECT_VALUE = updateXML(OBJECT_VALUE, '/PurchaseOrder/User/text()', 'SVOLLMAN')
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
1 row updated.
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User')
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
EXTRACTVAL
----------
SVOLLMAN
1 row selected.
例7-3 UPDATEXMLでのXPathリライトによるリライト済オブジェクト・リレーショナル文
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User') FROM purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1; EXTRACTVAL ---------- SBELL 1 row selected. UPDATE purchaseorder p SET p."XMLDATA"."userid" = 'SVOLLMAN' WHERE p."XMLDATA"."reference" = 'SBELL-2002100912333601PDT'; 1 row updated. SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User') FROM purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1; EXTRACTVAL ---------- SVOLLMAN 1 row selected.
|
関連項目: XML Schemaに基づくビューおよびXML Schemaに基づかないビューに対する他のXPathリライト例は、第3章「Oracle XML DBの使用」の「XPathリライトの理解および最適化」を参照してください。 |
XPathリライトは、次のSQL関数に対して行われます。
deleteXML
existsNode
extract
extractValue
insertChildXML
updateXML
XMLExists
XMLQuery
XMLSequence
XMLTable
XPathリライトは、問合せ、DML文またはDDL文のいずれかの式にこれらのSQL関数が存在している場合に行われます。たとえば、関数extractValueを使用して、基礎となるリレーショナル列に対する索引を作成できます。
例7-4 SELECT文とXPathリライト
この例では、既存の発注書を戻します。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') FROM mypurchaseorders x WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder/Item[1]/Part') = 1;
例7-5および例7-6に、基礎となる列を使用するようにリライトされる文をいくつか示します。例7-5は、CompanyがOracleでないすべてのPurchaseOrder要素を削除します。
例7-5 DML文とXPathリライト
DELETE FROM mypurchaseorders x WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') = 'Oracle Corp';
例7-6はCompany列に索引を作成します。
例7-6 CREATE INDEX文とXPathリライト
CREATE INDEX company_index ON mypurchaseorders e (extractValue(OBJECT_VALUE,'/PurchaseOrder/Company'));
Company列はオブジェクト・リレーショナル形式で格納されているため、XPathリライトが行われると、基礎となるリレーショナル列に対して索引が作成されます。この場合、SQL関数のリライトによって単純なリレーショナル列が生成されると、索引は、ファンクション索引ではなくBツリーまたは列に対するドメイン索引に変換されます。
通常、次のすべての条件が満たされている場合に、XPath式はリライト可能です。
SQL関数またはXMLTypeメソッドがリライト可能な場合。
SQL関数XMLQuery、XMLTable、XMLExists、extract、existsNode、extractValue、updateXML、insertChildXML、deleteXMLおよびXMLSequenceがリライトされます。メソッドexistsNode()およびextract()を除き、対応するXMLTypeメソッドはいずれもリライトできません。
XPath式がdescendant軸のみを使用している場合。
descendant以外の軸(parent軸やsibling軸など)が含まれている式は、リライトできません。属性、要素またはテキストのノードを選択する式は、リライト可能です。XPath述語は、SQL述語にリライトできます。
XPath式のXML Schema構造体がリライト可能な場合。
複合型、列挙値、リスト、継承(導出)された型、代替グループなどのXML Schema構造体がリライトできます。
XML Schemaの登録時に選択された記憶域構造がリライト可能な場合。
オブジェクト・リレーショナル形式(構造化記憶域)で格納されたXMLデータはリライトできます。CLOBインスタンス(ハイブリッド記憶域)を使用する複合型の記憶域はリライトできません。
表7-1に、基礎となるSQL問合せに変換できるXPath式の一部の種類を示します。
表7-1 基礎となるSQL構造体にリライトされるXPath式のサンプル・リスト
| 変換されるXPath式 | 説明 |
|---|---|
|
単純なXPath式:
|
属性自体が単純なスカラー型またはオブジェクト型である場合、オブジェクト型の属性のみに対して全検索が行われます。サポートされる軸は、child軸およびattribute軸のみです。 |
|
コレクション全検索式:
|
コレクション式の全検索が行われます。サポートされる軸は、child軸およびattribute軸のみです。 |
|
述語:
|
XPathの述語は、SQL述語にリライトされます。 |
|
リスト索引(位置指定述語):
|
コレクションのn番目の項目にアクセスするように索引がリライトされます。 |
|
ワイルド・カード全検索:
|
ワイルド・カードを一意のXPathに変換できる場合(たとえば、 |
|
descendant軸(XML Schemaに基づくデータのみ):
|
ワイルド・カード式と同様です。descendent軸が一意のXPath式にマップされ、後続する要素が再帰型の定義に含まれていない場合は、descendent軸がリライトされます。ただし、再帰型の定義が存在しても、リライトできる場合があります。 |
|
Oracleで提供する拡張関数およびいくつかのXPath関数
|
Oracle XML DBの名前空間( |
|
述語内の文字列バインド変数
|
連結演算子( |
|
|
|
脚注1 tableとXMLSequenceを使用するかわりに、よりわかりやすい標準のSQL/XML関数XMLTableを使用することもできます。
complexType要素やシーケンスなどの標準的なXML Schema構造体に加え、次のXML Schema構造体もサポートされます。これは完全なリストではありません。
述語にスカラー値が使用されているスカラー値のコレクション。
属性を含んでいる単純型の拡張。
列挙単純型。
ブール単純型。
複合型の継承。
代用グループ。
次のXML Schema構造体はサポートされません。XPath式に次のXML Schema構造体を持つノードが含まれている場合、式はリライトされません。
anyコンテンツを含む要素の子にアクセスするXPath式。ノードにanyコンテンツが含まれる場合、XPathに指定された名前空間以外の名前空間をanyがターゲットとする場合を除き、式はリライトされません。any属性も同様の方法で処理されます。
ブール値と数値の合計など、強制変換できないデータ型の操作。
リライトされたXPath問合せと機能的に評価されたXPath問合せは、ほとんど差異がありません。ただし、XPathのリライトはXML Schema情報を使用してXPath述語をSQL述語に変換するため、数値以外のエンティティの比較には差異があります。
XPath 1.0で、比較演算子>、<、>=および<=は、数値の比較のみに使用します。2つのオペランドは、比較の前に数値に変換されます。数値への変換のいずれかが失敗した場合、比較の結果としてfalseが戻ります。
たとえば、XML Schemaに基づく次のような要素定義の場合、[ShipDate < '2003-02-01']などのXPath述語は常に、機能上の評価でfalseに評価されます。
<element name="ShipDate" type="xs:date" xdb:SQLType="DATE"/>
これは、文字列'2003-02-01'を数量に変換できないためです。一方、XPathリライトでは、この述語はSQLの日付比較に変換され、ShipDateの値に従ってtrueまたはfalseに評価されます。
同様に、別のコレクション値と比較するコレクション値がある場合、XPath 1.0のセマンティクスでは、値を文字列に変換してから比較する必要があります。ただしXPathリライトでは、SQLの値を比較するためのルールを使用して比較が行われます。
比較動作の違いを抑制する場合は、問合せのヒントまたはセッション・レベルのイベントを使用してリライトを無効にできます。
この項では、この章で前出の発注書XML Schemaを使用します。
例7-7 XML Schemaに基づく発注データの作成
DECLARE
doc VARCHAR2(2000) :=
'<schema
targetNamespace="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd"
xmlns:po="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<complexType name="PurchaseOrderType">
<sequence>
<element name="PONum" type="decimal"/>
<element name="Company">
<simpleType>
<restriction base="string">
<maxLength value="100"/>
</restriction>
</simpleType>
</element>
<element name="Item" maxOccurs="1000">
<complexType>
<sequence>
<element name="Part">
<simpleType>
<restriction base="string">
<maxLength value="20"/>
</restriction>
</simpleType>
</element>
<element name="Price" type="float"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
<element name="PurchaseOrder" type="po:PurchaseOrderType"/>
</schema>';
BEGIN
DBMS_XMLSCHEMA.registerSchema(
'http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd', doc);
END;
/
XML Schema登録では、内部的なSQLデータ型が作成されます。これによって、XML値を格納する表およびItemを格納するOrdered Collection Tableを作成できるようになりました。
CREATE TABLE mypurchaseorders OF XMLType XMLSchema "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd" ELEMENT "PurchaseOrder" VARRAY XMLDATA."Item" STORE AS TABLE item_nested; Table created
次に、発注書をこの表に挿入します。
INSERT INTO mypurchaseorders
VALUES(
XMLType(
'<PurchaseOrder
xmlns="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
= "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd
http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd">
<PONum>1001</PONum>
<Company>Oracle Corp</Company>
<Item>
<Part>9i Doc Set</Part>
<Price>2550</Price>
</Item>
<Item>
<Part>8i Doc Set</Part>
<Price>350</Price>
</Item>
</PurchaseOrder>'));
XML Schemaでは順序の保持についての情報が指定されていないため、デフォルト動作では、順序およびDOM再現性が保持されます。したがって、型には、ノードの順序を保持し、コメントや処理命令などの追加項目を取得するのに必要な追加情報を格納するためのSYS_XDBPD$(PD)属性が含まれます。
オブジェクト属性SYS_XDBPD$には、要素の有無を示す情報(入力ドキュメントに要素が存在したかどうか)も保持されます。simpleType要素の場合は単純なリレーショナル列にマップされるため、この情報が必要です。空のsimpleType要素と欠落しているsimpleType要素の両方が列のNULL値にマップされます。この2つを区別するには、SYS_XDBPD$属性を使用できます。XPathリライト・メカニズムでは属性SYS_XDBPD$の有無が考慮され、問合せが適切にリライトされます。
この表には、実際のデータを格納するpurchaseorder_tという型の疑似列XMLDATAが含まれます。
この項では、XPath式からSQLデータ型とパス式へのマッピングについて説明します。
XPath式には、要素のテキスト・ノード(コンテンツ)をターゲットとするtext()ノード・テストを含めることができます。リライトによって、この式は基礎となるリレーショナル列に直接マップされます。たとえば、XPath式/PurchaseOrder/PONum/text()は、SQL列XMLDATA."PONum"に直接マップされます。
PONum列のNULL値は、入力ドキュメントにtext()ノード・テストが存在しないか、または要素自体が欠落しているため、テキスト値が使用できないことを意味します。列がNULLの場合、SYS_XBDPD$属性で要素の有無を確認する必要はありません。
XPath /PurchaseOrder/PONumも、SQL列XMLDATA."PONum"にマップされます。ただし、この場合、XPathリライトで、XMLDATA列のSYS_XDBPD$属性を使用して要素自体の有無を確認する必要があります。
XPath述語は、SQL述語式にマップされます。比較では、XPath 1.0セマンティクスにでなくSQLの比較規則が使用されます。「XPathリライトによる比較セマンティクスの変更」を参照してください。
たとえば、XPath式/PurchaseOrder[PONum=1001 and Company = "Oracle Corp"]の述語はSQL述語(XMLDATA."PONum" = 20 AND XMLDATA."Company" = "Oracle Corp")にマップされます。
例7-8 述語のマッピング
この問合せは、構造化された(オブジェクト・リレーショナルな)問合せにリライトされます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item').getCLOBval()
FROM mypurchaseorders p
WHERE existsNode(OBJECT_VALUE,
'/PurchaseOrder[PONum=1001 AND Company = "Oracle Corp"]') = 1;
コレクション述語のマッピングXPath式に、リレーショナル・コレクション式が含まれていることがあります。Xpath 1.0では、これらの式は要素の有無の確認として処理されます。少なくとも1つのコレクション・メンバーが式に含まれている場合、その式はtrueです。
例7-9 コレクション述語のマッピング
このXPath式のコレクション述語には、リレーショナルの大なり演算子(>)が含まれています。
/PurchaseOrder[Items/Price > 200]
これは、次のSQLコレクション式にマップされます。
exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE x."Price" > 200)
この例では、コレクションがスカラー値に関連付けられています。2つのコレクションに関連がある場合、リライトは複雑になります。たとえば、次のXPath式では、LineItemsとShippedItemsはいずれもコレクションです。
/PurchaseOrder[LineItems = ShippedItems]
この場合、この2つのコレクションからのノードのいずれかの組合せが等価性を満たしていれば、その述語が等価性を満たしていると判断されます。
例7-10 EXISTSNODEを使用したコレクション述語のマッピング
PurchaseorderにPriceとPartの数値が同じであるItemが存在するかどうかを確認するXPath、/PurchaseOrder[Items/Price = Items/Part]を考えてみます。これは、次のSQLコレクション式にマップされます。
EXISTS (SELECT NULL
FROM table(XMLDATA."Item") x
WHERE EXISTS (SELECT NULL FROM table(XMLDATA."Item") y
WHERE y."Part" = x."Price"))
次の問合せは、構造化された問合せにリライトされます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item').getCLOBval() FROM mypurchaseorders p WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Item/Price = Item/Part]') = 1;
ほとんどのリライトでは、元のドキュメント内の順序が保持されます。ただし、SQLでは副問合せの結果における順序の保持が保証されないため、SQL関数extractを使用してコレクションから要素を選択すると、ノードの順序がドキュメント内の順序と異なる場合があります。
例7-11 コレクション全検索でのドキュメント内の順序の保持
次に例を示します。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item[Price>2100]/Part') FROM mypurchaseorders p;
この問合せは、副問合せを使用するようにリライトされます。
SELECT (SELECT XMLAgg(XMLForest(x."Part" AS "Part"))
FROM table(XMLDATA."Item") x WHERE x."Price" > 2100)
FROM mypurchaseorders p;
ほとんどの場合、集計の結果はコレクション要素と同じ順序になりますが、これが保証されているわけではありません。したがって、結果がドキュメント順序とは異なる場合もあります。
XPath式で、コレクションの特定位置にある要素にアクセスすることもできます。たとえば、/PurchaseOrder/Item[1]/Partは、コレクションの最初のItemを抽出し、その中のPart属性にアクセスするようにリライトされます。
コレクションがVARRAY値として格納されている場合は、この操作によって元のドキュメント内の順序でノードが取得されます。コレクションが順序付けられていない表に格納されている場合、順序は判別不能です。
XPath式には、入力ドキュメントに含めることができないノードに対する参照が含まれる場合があります。式のこのような部分は、リライト時にSQLのNULL値にマップされます。たとえば、/PurchaseOrder/ShipAddressというXPath式は、purchaseorder.xsdというXML Schemaに準拠するインスタンス・ドキュメントの条件を満たすことができません。これは、スキーマでPurchaseOrderのShipAddress要素が許可されないためです。したがって、この式はSQLのNULLリテラルにマップされます。
名前空間は、関数ベースの評価と同じ方法で処理されます。XML Schemaに基づく文書の場合、関数(existsNodeやextractなど)によって名前空間パラメータが指定されないと、スキーマのターゲットの名前空間がXPath式のデフォルトの名前空間として使用されます。
例7-12 名前空間の処理
たとえば、SQL関数によって名前空間の接頭辞およびマッピングが明示的に指定されない場合、XPath式/PurchaseOrder/PONumは、xmlns:a= "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsdで/a:PurchaseOrder/a:PONumとして処理されます。別の例を示します。
SELECT * FROM mypurchaseorders p WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1;
これは、次の問合せと同等の結果を戻します。
SELECT *
FROM mypurchaseorders p
WHERE existsNode(
OBJECT_VALUE,
'/PurchaseOrder/PONum',
'xmlns="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd')
= 1;
XPathリライトを実行すると、特定の要素に対する名前空間はXML Schema定義の名前空間と一致します。XML SchemaにelementFormDefault = "qualified"が含まれる場合、XPath式の各ノードは名前空間をターゲットとする必要があります(これは、デフォルトの名前空間の指定を使用するか、または各ノードに名前空間の接頭辞を付けることで実行できます)。
elementFormDefaultが非修飾(デフォルト)である場合、名前空間を定義するノードのみに接頭辞が含まれる必要があります。たとえば、purchaseorder.xsdの要素形式が非修飾の場合は、existsNode式を次のようにリライトする必要があります。
existsNode( OBJECT_VALUE, '/a:PurchaseOrder/PONum', 'xmlns:a="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd") = 1;
|
注意: elementFormDefaultが非修飾である場合、前述の例のexistsNode式で名前空間パラメータを省略すると、各ノードがデフォルトでターゲットの名前空間に設定されます。これは、XML Schema定義に一致しないために、結果が戻されない場合があります。これは、関数がリライトされるかどうかに関係ありません。 |
date、gMonthおよびgDateの日付データ型の書式は、XML SchemaとSQLで異なります。このようなデータ型の列に対する文字列値が式に含まれていると、リライトによってXML形式の文字列が自動的に挿入され、文字列値が正しく変換されます。このため、date列に指定された文字列値は、SQLのDATE書式ではなく、XMLのdate書式に一致している必要があります。
例7-13 日付書式の変換
たとえば、式[@PurchaseDate="2002-02-01"]は単にXMLDATA."PurchaseDate"="2002-02-01"としてはリライトされません。これは、SQLのデフォルトの日付書式がYYYY-MM-DDでないためです。したがって、XPathのリライト時に、XML形式の文字列が追加され、テキスト値がDATEデータ型に正しく変換されます。前述の述語は、次のとおりリライトされます。
XMLDATA."PurchaseDate" = TO_DATE("2002-02-01","SYYYY-MM-DD");
同様に、これらの列を(extractなどの関数に必要な)テキスト値に変換する際に、XML形式の文字列が追加されてXMLと同じ日付書式に変換されます。
SQL関数existsNodeは、XPathで指定されているノードの有無を確認します。関数extractは、XPathで指定されているノードを戻します。Oracle XML DBは、simpleType要素に対して、およびexistsNode式で使用されている属性に対して、特別なチェックを実行する必要があります。これは、SQL列の値が単独では属性またはsimpleType要素が欠落していたり、空であることを識別できないためです。NULLのSQL列は、いずれも表すことができます。中間要素の場合は、ユーザー定義のSQLデータ型によって、その要素が欠落していること、または空であることが示されるため、これらの特別なチェックは不要です。
たとえば、次の式について考えてみます。
existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum/text()') = 1;
問合せがノードのテキスト値のみを対象としているため、この式は次のようにリライトされます。
(p.XMLDATA."PONum" IS NOT NULL)
次に、text()ノード・テストのない式について考えてみます。
existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1;
この場合、Oracle XML DBは、親ノードのSYS_XDBPD$属性をチェックして、要素が空または欠落しているかどうかを判断する必要があります。このチェックは内部で実行されます。これは、次のような擬似コードで表すことができます。
node_exists(p.XMLDATA."SYS_XDBPD$", "PONum")
擬似関数node_existsは、説明のためのみに使用しています。これは、最初の引数である位置指定ディスクリプタ(PD)列(SYS_XDBPD$)を使用して2番目の引数(要素または属性)のノードが存在するかどうかを判別する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
extract式の場合は、属性および要素の両方に対してこのチェックを実行する必要があります。extract(OBJECT_VALUE, '/PurchaseOrder/PONum')という形式の式は、次のような擬似コードにマップされます。
CASE WHEN node_exists(p.XMLDATA.SYS_XDBPD$", "PONum")
THEN XMLElement("PONum", p.XMLDATA."PONum")
ELSE NULL END;
|
注意: existsNodeまたはextract式を記述する場合は、このオーバーヘッドに注意してください。このオーバーヘッドを回避するには、XPath式のtext()ノード・テストを使用するか、extractValueを使用してノードの値のみを取得するか、あるいは親ノードのDOM再現性を無効にします。DOM再現性は、要素定義のmaintainDOM属性の値をfalseに設定することで無効にできます。無効にした場合、空の要素および属性は欠落しているとして処理されます。 |
この項では、XPath式が実際にリライトされているかどうかを判断するテクニックを紹介します。
この項では、EXPLAIN PLANを使用して、XPathリライト後に問合せ計画を調べる方法について説明します。EXPLAIN PLANを使用してXPathリライトを最適化する方法の詳細は、「XPathリライトの理解および最適化」を参照してください。
問合せ評価計画で、適用可能な索引が選択されずにSQL関数(existsNode、extractなど)の存在が示された場合は、リライトが発生しなかったことがわかります。その後、イベントを使用して、XPathリライトが発生しなかった理由を理解できます。「XPathでのイベントの使用」を参照してください。
たとえば、表mypurchaseordersを使用して、EXPLAIN PLANの使用を確認できます。PurchaseOrderのCompany要素に対して索引を作成し、計画の違いを確認します。
CREATE INDEX company_index ON mypurchaseorders
(extractValue(OBJECT_VALUE,'/PurchaseOrder/Company'));
Index created.
EXPLAIN PLAN FOR
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum')
FROM mypurchaseorders
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company="Oracle"]') = 1;
Explained.
SELECT PLAN_TABLE_OUTPUT
FROM table(DBMS_XPLAN.display('plan_table', NULL, 'serial'))
/
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | |
| 1 | TABLE ACCESS BY INDEX ROWID | MYPURCHASEORDERS | | | |
|* 2 | INDEX RANGE SCAN | COMPANY_INDEX | | | |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("MYPURCHASEORDERS"."SYS_NC00010$"='Oracle')
このEXPLAIN PLANでは、述語が内部列を使用しており、Company要素に対する索引を選択していることを確認できます。これは、問合せが基礎となるリレーショナル列にリライトされたことを示しています。
次の問合せは、文字列型であるCompany要素に対して算術演算を実行しようとしています。これはリライトされません。EXPLAIN PLANは述語に元のexistsNode式が含まれていることを示しています。また、述語はリライトされないため、索引レンジ・スキャンではなく、全表スキャンが使用されます。
EXPLAIN PLAN FOR
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum')
FROM mypurchaseorders
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+PONum="Oracle"]') = 1;
Explained.
SELECT PLAN_TABLE_OUTPUT
FROM table(DBMS_XPLAN.display('plan_table', NULL, 'serial'))/
PLAN_TABLE_OUTPUT
-----------------------------------------------------------
| Id | Operation | Name
-----------------------------------------------------------
| 0 | SELECT STATEMENT |
|* 1 | FILTER |
| 2 | TABLE ACCESS FULL| MYPURCHASEORDERS
|* 3 | TABLE ACCESS FULL| ITEM_NESTED
-----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(EXISTSNODE(SYS_MAKEXML('C6DB2B4A1A3B0
6CDE034080020E5CF39',2300,"MYPURCHASEORDERS"."XMLEXTRA",
"MYPURCHASEORDERS"."XMLDATA"),
'/PurchaseOrder[Company+PONum="Oracle"]')=1)
3 - filter("NESTED_TABLE_ID"=:B1)
イベントは、初期化ファイルに設定するか、またはALTER SESSION文を使用して各セッションに設定できます。XMLイベントを使用すると、機能上の評価やXPathリライト・メカニズムを無効にしたり、診断トレースを印刷できます。
このイベントを使用可能にすることで、XML関数がリライトされずに機能上の評価が行われる場合には、常にエラーが発行されるようにできます。このような関数が実行されると、エラー「ORA-19022: XML XPath機能は使用できません」が発行されます。また、このイベントを使用して、関数に対する機能上の評価を選択して無効にすることもできます。表7-3に、様々なイベント・レベルおよび対応する動作をリストします。
表7-3 イベントのレベルおよび動作
| イベント | 機能上の評価が無効になる関数 |
|---|---|
|
レベル0x1 |
すべてのXML関数 |
|
レベル0x2 |
|
|
レベル0x4 |
|
|
レベル0x8 |
|
|
レベル0x10 |
|
|
レベル0x20 |
|
|
レベル0x40 |
|
|
レベル0x80 |
|
|
レベル0x100 |
|
|
レベル0x200 |
|
|
レベル0x4000 |
|
|
レベル0x8000 |
|
次に例を示します。
ALTER SESSION SET EVENTS '19021 trace name context forever, level 1';
この場合、前述のすべてのXML演算子の評価が無効になります。したがって、リライトされていない前述の問合せを実行すると、問合せの実行でエラーが発生します。
SELECT OBJECT_VALUE FROM mypurchaseorders WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+PONum="Oracle"]')=1 ; ERROR: ORA-19022: XML XPath functions are disabled
8192(0x2000)レベルのイベント19027を使用すると、特定のXML関数がリライトされていない理由を示すトレースをダンプできます。たとえば、前述の問合せがリライトされなかった理由を調べる場合は、イベントを設定してEXPLAIN PLANを実行します。
ALTER SESSION SET EVENTS '19027 TRACE NAME CONTEXT FOREVER, LEVEL 8192';
Session altered.
EXPLAIN PLAN FOR
SELECT OBJECT_VALUE FROM mypurchaseorders
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+100="Oracle"]') = 1;
Explained.
次の記述は、算術関数に対する数値以外の入力が原因でXPathのリライトが生じなかったことを示すOracleのトレース・ファイルです。
NO REWRITE
XPath ==> /PurchaseOrder[Company+PONum = "Oracle"] Reason ==> non numeric inputs to arith{2}{4}
この項では、SQL関数existsNode、extractValue、extract、XMLSequence、updateXML、insertChildXMLおよびdeleteXMLに対するXPathリライトについて詳しく説明します。existsNodeまたはextractを使用する特定タイプの操作で発生するオーバーヘッドと、それを回避する方法について説明します。
これらのSQL関数を使用する更新では、通常、XML文書のコピーが更新されてから、新しく変更された文書で文書全体が置換されます。
XMLTypeデータがXML Schemaマッピングを使用してオブジェクト・リレーショナル形式で格納されている場合は、文書の断片がインプレース変更されるように更新が最適化されます。たとえば、PONum要素を更新する場合、メモリー内で文書全体を生成した後に更新を実行するのではなく、列XMLDATA."PONum"が直接更新されるようにリライトできます。
更新時にこのようなリライト最適化を使用するには、関数updateXML、insertChildXMLおよびdeleteXMLがそれぞれ別の条件を満たしている必要があります。前述のすべての条件が満たされる場合、ファンクション式は単純なリレーショナル更新にリライトされます。次に例を示します。
UPDATE purchaseorder_table
SET OBJECT_VALUE =
updateXML(OBJECT_VALUE,
'/PurchaseOrder/@PurchaseDate', '2002-01-02',
'/PurchaseOrder/PONum/text()', 2200);
この更新操作は、次のようにリライトされます。
UPDATE purchaseorder_table p
SET p.XMLDATA."PurchaseDate" = TO_DATE('2002-01-02', 'SYYYY-MM-DD'),
p.XMLDATA."PONum" = 2100;
XPath引数が空でないノード(テキスト、要素または属性)のシーケンスをターゲットにしている場合、SQL関数existsNodeは1を戻します。そうでない場合は、0(ゼロ)を戻します。値の判別方法は、XPath引数でターゲットになっているノードの種類によって異なります。
XPath引数が(ノード・テストtext()を使用する)テキスト・ノードまたはcomplexType要素ノードをターゲットにしている場合、Oracle XML DBは、要素のコンテンツのデータベース表示がNULLであるかどうかをチェックするのみです。
それ以外の場合、XPath引数はsimpleType要素ノードまたは属性ノードをターゲットにしています。Oracle XML DBは、位置指定ディスクリプタ属性SYS_XDBPD$を使用してノードの有無を確認します。SYS_XDBPD$属性が存在しない場合は、列がNULLかどうかを調べることによってノードの有無が判断されます。
表7-4に、ドキュメント内の順序が保持される(SYS_XDBPD$が存在し、スキーマ・ドキュメントでmaintainDOM = "true"が設定されている)場合の、SQL関数existsNodeでの様々なXPath式のマッピングを示します。
表7-4 ドキュメント内の順序が保持されるEXISTSNODEのXPathマッピング
| XPath式 | マップ先 |
|---|---|
/PurchaseOrder |
CASE WHEN XMLDATA IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/@PurchaseDate |
CASE WHEN node_exists脚注1 (XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN 1 ELSE 0 END |
/PurchaseOrder/PONum |
CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PONum') THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100] |
CASE WHEN XMLDATA."PONum"=2100 THEN 1 ELSE 0 |
/PurchaseOrder[PONum = 2100]/@PurchaseDate |
CASE WHEN XMLDATA."PONum"=2100
AND node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PurchaseDate')
THEN 1 ELSE 0 END
|
/PurchaseOrder/PONum/text() |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 |
/PurchaseOrder/Item |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE value(x) IS NOT NULL)
THEN 1 ELSE 0 END
|
/PurchaseOrder/Item/Part |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE node_exists脚注1(x.SYS_XDBPD$, 'Part'))
THEN 1 ELSE 0 END
|
/PurchaseOrder/Item/Part/text() |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE x."Part" IS NOT NULL)
THEN 1 ELSE 0 END
|
脚注1 擬似関数node_existsは、説明のためのみに使用しています。これは、最初の引数であるPD列を使用して2番目の引数のノードが存在するかどうかを判断する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
例7-14 ドキュメント内の順序が保持されるEXISTSNODEのマッピング
この問合せでは、前述のマッピングを使用して、発注1001に価格が2000を超える部品が存在するかどうかを確認します。
SELECT count(*)
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE,
'/PurchaseOrder[PONum=1001 and Item/Price > 2000]') = 1;
この問合せは、次のようにリライトされます。
SELECT count(*)
FROM purchaseorder p
WHERE CASE WHEN p.XMLDATA."PONum" = 1001
AND exists(SELECT NULL FROM table(XMLDATA."Item") p
WHERE p."Price" > 2000 ))
THEN 1
ELSE 0
END = 1;
このCASE式は、さらに定数関係式によって最適化されます。問合せは、次のように再作成されます。
SELECT count(*)
FROM purchaseorder p
WHERE p.XMLDATA."PONum"=1001
AND exists(SELECT NULL FROM table(p.XMLDATA."Item") x
WHERE x."Price" > 2000);
Part列およびPONum列にリレーショナル索引が存在する場合、そのリレーショナル索引を使用して評価が行われます。
位置指定ディスクリプタ属性SYS_XDBPD$が存在しない場合(つまり、XML SchemaでmaintainDOM = "false"が指定されている場合)、NULLスカラー列が、存在しないsimpleType要素にマップされます。その場合、属性SYS_XDBPD$を使用してノードの有無を確認する必要はありません。表7-5に、SYS_XDBPD$属性がない場合のexistsNodeのマッピングを示します。
表7-5 ドキュメント内の順序が保持されないEXISTSNODEのXPathマッピング
| XPath式 | マップ先 |
|---|---|
/PurchaseOrder |
CASE WHEN XMLDATA IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/@PurchaseDate |
CASE WHEN XMLDATA.'PurchaseDate' IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/PONum |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100] |
CASE WHEN XMLDATA."PONum" = 2100 THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100]/@PurchaseOrderDate |
CASE WHEN XMLDATA."PONum" = 2100
AND XMLDATA."PurchaseDate" NOT NULL
THEN 1 ELSE 0 END
|
/PurchaseOrder/PONum/text() |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/Item |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE value(x) IS NOT NULL)
THEN 1 ELSE 0 END
|
/PurchaseOrder/Item/Part |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE x."Part" IS NOT NULL)
THEN 1 ELSE 0 END
|
/PurchaseOrder/Item/Part/text() |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x
WHERE x."Part" IS NOT NULL)
THEN 1 ELSE 0 END
|
SQL関数extractValueは、関数extractを使用してテキスト・ノードおよび属性を抽出し、次にメソッドgetStringVal()またはgetNumberVal()を使用してスカラー・コンテンツを取得するためのショートカットです。関数extractValueは、スカラー値を持つ要素の属性ノードまたはテキスト・ノードの値を戻します。関数extractValueは、複数の値またはcomplexType要素を戻すXPath式を処理できません。
表7-6に、関数extractValueでの様々なXPath式のマッピングを示します。XPath式が要素をターゲットとしている場合は、extractValueによって要素のテキスト・ノードが取得されます。たとえば、/PurchaseOrder/PONumおよび/PurchaseOrder/PONum/text()はextractValueによって同じ方法で処理されます。どちらも、PONumのスカラー・コンテンツを取得します。
| XPath式 | マップ先 |
|---|---|
/PurchaseOrder |
サポートされていません。関数 |
/PurchaseOrder/@PurchaseDate |
XMLDATA."PurchaseDate" |
/PurchaseOrder/PONum |
XMLDATA."PONum" |
/PurchaseOrder[PONum = 2100] |
(SELECT TO_XML(x.XMLDATA) FROM DUAL WHERE x."PONum" = 2100) |
/PurchaseOrder[PONum =
2100]/@PurchaseDate
|
(SELECT x.XMLDATA."PurchaseDate") FROM DUAL WHERE x."PONum" = 2100) |
/PurchaseOrder/PONum/text() |
XMLDATA."PONum" |
/PurchaseOrder/Item |
サポートされていません。関数 |
/PurchaseOrder/Item/Part |
サポートされていません。関数 |
/PurchaseOrder/Item/Part/text() |
サポートされていません。関数 |
例7-15 EXTRACTVALUEのリライト
次のSQL問合せについて考えてみます。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') FROM purchaseorder WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1001;
この問合せは、次のようにリライトされます。
SELECT p.XMLDATA."PONum" FROM purchaseorder p WHERE p.XMLDATA."PONum" = 1001;
これは単純なスカラー列にリライトされるため、属性PONumに対する索引があれば、問合せの条件を満たすためにそれを使用できます。
EXTRACTVALUEを使用した索引の作成
関数extractValueは、索引式で使用できます。式がスカラー列にリライトされると、索引はファンクション索引ではなくBツリー索引に変換されます。
例7-16 EXTRACTVALUEを使用した索引の作成
CREATE INDEX my_po_index ON purchaseorder (extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference);
これは、次のようにリライトされます。
CREATE INDEX my_po_index ON purchaseorder x (x.XMLDATA."Reference");
これによって、通常のBツリー索引が生成されます。ファンクション索引とは異なり、同じ索引で次のような列をターゲットとする問合せの条件を満たすことができるようになります。
existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
SQL関数extractは、XPathの結果をXMLとして取得します。テキスト・ノードが含まれるXpath式の場合、extractは同様にextractValueにリライトされます。
表7-7に、ドキュメント内の順序が保持される場合(SYS_XDBPD$が存在し、XML SchemaドキュメントでmaintainDOM = "true"が設定されている場合)の、extract式内部の様々なXPath式のマッピングを示します。
表7-7 ドキュメント内の順序が保持されるEXTRACTのXPathマッピング
| XPath | マップ先 |
|---|---|
/PurchaseOrder |
XMLForest(XMLDATA AS "PurchaseOrder") |
/PurchaseOrder/@PurchaseDate |
CASE WHEN node_exists脚注1 (XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN XMLElement("", XMLDATA."PurchaseDate") ELSE NULL END; |
/PurchaseOrder/PONum |
CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PONum') THEN XMLElement("PONum", XMLDATA."PONum") ELSE NULL END |
/PurchaseOrder[PONum = 2100] |
SELECT XMLForest(XMLDATA as "PurchaseOrder") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder [PONum = 2100]/@PurchaseDate |
SELECT CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN XMLElement("", XMLDATA."PurchaseDate") ELSE NULL END FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder/PONum/text() |
XMLElement("", XMLDATA."PONum")
|
/PurchaseOrder/Item |
SELECT XMLAgg(XMLForest(value(it) AS "Item")) FROM table(XMLDATA."Item") it |
/PurchaseOrder/Item/Part |
SELECT XMLAgg(CASE WHEN node_exists脚注1(p.SYS_XDBPD$, 'Part') THEN XMLForest(p."Part" AS "Part") ELSE NULL END) FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part/text() |
SELECT XMLAgg(XMLElement("", p."Part"))
FROM table(XMLDATA."Item") p
|
脚注1 擬似関数node_existsは、説明のためのみに使用しています。これは、最初の引数であるPD列を使用して2番目の引数のノードが存在するかどうかを判断する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
例7-17 ドキュメント内の順序が保持されるEXTRACTのXPathマッピング
表7-7に示すマッピングを使用して、発注書に価格が2000を超える部品が含まれるPONum要素を抽出する次の問合せを考えてみます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder[Item/Part > 2000]/PONum') FROM purchaseorder_table;
この問合せは、次のようになります。
SELECT (SELECT CASE WHEN node_exists(p.XMLDATA.SYS_XDBPD$, 'PONum')
THEN XMLElement("PONum", p.XMLDATA."PONum")
ELSE NULL END
FROM DUAL
WHERE exists(SELECT NULL FROM table(XMLDATA."Item") p
WHERE p."Part" > 2000))
FROM purchaseorder_table p;
属性SYS_XDBPD$が存在しない場合(つまり、XML SchemaでmaintainDOM = "false"が指定されている場合)、NULLスカラー列が、存在しないsimpleType要素にマップされます。したがって、属性SYS_XDBPD$を使用してノードの有無を確認する必要はありません。表7-8に、SYS_XDBPD$がない場合の関数existsNodeのマッピングを示します。
表7-8 ドキュメント内の順序が保持されないEXTRACTのXPathマッピング
| XPath | マップ先 |
|---|---|
/PurchaseOrder |
XMLForest(XMLDATA AS "PurchaseOrder") |
/PurchaseOrder/@PurchaseDate |
XMLForest(XMLDATA."PurchaseDate" AS "PurchaseDate") |
/PurchaseOrder/PONum |
XMLForest(XMLDATA."PONum" AS "PONum") |
/PurchaseOrder[PONum = 2100] |
SELECT XMLForest(XMLDATA AS "PurchaseOrder") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder [PONum = 2100]/@PurchaseDate |
SELECT XMLForest(XMLDATA."PurchaseDate" AS "PurchaseDate "") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder/PONum/text() |
XMLForest(XMLDATA.PONum AS "") |
/PurchaseOrder/Item |
SELECT XMLAgg(XMLForest(value(p) AS "Item") FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part |
SELECT XMLAgg(XMLForest(p."Part" AS "Part") FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part/text() |
SELECT XMLAgg(XMLForest(p. "Part" AS "Part")) FROM table(XMLDATA."Item") p |
SQL関数XMLSequenceをSQL関数extractおよびtableと組み合せて使用すると、XMLのコレクション値をネスト解除できます。脚注1 XML Schemaに基づく記憶域で使用されている場合、これらの関数も、基礎となるリレーショナル・コレクション記憶域にアクセスするようにリライトされます。
たとえば、この問合せは、全品目の価格と部品番号をリレーショナル形式で取得します。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum,
extractValue(value(it), '/Item/Part') AS part,
extractValue(value(it), '/Item/Price') AS price
FROM purchaseorder,
table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it;
PONUM PART PRICE
----- -------------------- ---------
1001 9i Doc Set 2550
1001 8i Doc Set 350
この例では、SQL関数extractは、Item要素のリストを含むフラグメントを戻します。関数XMLSequenceは、Item要素ごとに、このフラグメントをXMLType値のコレクションに変換します。関数tableは、コレクションの要素をXMLTypeの行に変換します。tableから戻されたXMLデータは、Part要素およびPrice要素の抽出に使用されます。
関数extractおよびXMLSequenceを適用すると、Ordered Collection Table(OCT)のitem_nested上の単純なSELECT操作にリライトされます。
EXPLAIN PLAN
FOR SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum,
extractValue(value(it) , '/Item/Part') AS part,
extractValue(value(it), '/Item/Price') AS price
FROM purchaseorder,
table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it;
Explained
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | TABLE ACCESS FULL | ITEM_NESTED |
| 3 | TABLE ACCESS BY INDEX ROWID | PURCHASEORDER |
|* 4 | INDEX UNIQUE SCAN | SYS_C002973 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id)
--------------------------------------------------
4 - access("NESTED_TABLE_ID"="SYS_ALIAS_1"."SYS_NC0001100012$")
EXPLAIN PLANの出力は、オプティマイザがOCTのitem_nestedと表purchaseorderとの間の単純なネステッド・ループ結合を使用できることを示しています。Item値をさらに問い合せたり、OCTに適切な索引を作成して問合せを高速化することもできます。
たとえば、価格を検索して高価な品目すべてを取得するには、OCTのPrice列に対して索引を作成します。次のEXPLAIN PLANは、価格索引を使用して品目のリストを取得し、表purchaseorderと結合してPONum値を取得します。
CREATE INDEX price_index ON item_nested ("Price");
Index created.
EXPLAIN PLAN FOR
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum,
extractValue(value(it), '/Item/Part') AS part,
extractValue(value(it), '/Item/Price') AS price
FROM purchaseorder,
table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it
WHERE extractValue(value(it), '/Item/Price') > 2000;
Explained.
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | TABLE ACCESS BY INDEX ROWID | ITEM_NESTED |
|* 3 | INDEX RANGE SCAN | PRICE_INDEX |
| 4 | TABLE ACCESS BY INDEX ROWID | PURCHASEORDER |
|* 5 | INDEX UNIQUE SCAN | SYS_C002973 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ITEM_NESTED"."Price">2000)
5 - access("NESTED_TABLE_ID"="SYS_ALIAS_1"."SYS_NC0001100012$")
SQL関数updateXMLで最適化を使用するには、次の条件を満たす必要があります。
XMLType引数が登録済のXML Schemaに基づいていること。
XMLType引数がUPDATE操作のターゲットにもなっていること。次に例を示します。
UPDATE purchaseorder_table SET OBJECT_VALUE = updateXML(OBJECT_VALUE,...);
XPath引数がすべて異なっていること(重複がない)。
「リライトされるXPath式」で説明されているとおり、XPath引数がリライト可能であること。
XML SchemaでmaxOccurs <= 1を使用してマップされた要素をターゲットとするXPath引数は、スキーマ注釈maintainDom = falseが存在する場合にのみリライトされます。
XPath引数が、(XML Schemaで定義されているように)デフォルト値を持つノードをターゲットにしていないこと。
XPath引数が位置指定述語(たとえば、foo[2]など)を持たないこと。
XPath引数に述語が含まれる場合、述語がコレクションより前に出現しないこと。
たとえば、/PurchaseOrder/LineItems[@MyAtt="3"]/LineItemは、述語がLineItemコレクションよりも出現するため、リライトされません。(これは、LineItemsが属性MyAttを持つXML Schemaを想定しています。)
XPath式の引数がコレクションを参照している場合、そのコレクションが、個別のOrdered Collection Tableとして格納されているか、または表外(REF記憶域)に格納されていること(つまり表内に格納されていないこと)。
XPath引数がコレクションを参照している場合、そのコレクションがスカラー(maxOccurs > 1であるsimpleType)でないこと。
SQL関数deleteXMLで最適化を使用するには、次の条件を満たす必要があります。
XMLType引数が登録済のXML Schemaに基づいていること。
XMLType引数がUPDATE操作のターゲットにもなっていること。次に例を示します。
UPDATE purchaseorder_table SET OBJECT_VALUE = updateXML(OBJECT_VALUE,...);
「リライトされるXPath式」で説明されているとおり、XPath引数がリライト可能であること。
XPath引数が位置指定述語(たとえば、foo[2])を持たないこと。
XPath引数に述語が含まれる場合、述語がコレクションより前に出現しないこと。
たとえば、/PurchaseOrder/LineItems[@MyAtt="3"]/LineItemは、述語がLineItemコレクションよりも出現するため、リライトされません。(これは、LineItemsが属性MyAttを持つXML Schemaを想定しています。)
XPath引数が無制限のコレクション(maxOccurs = "unbounded"が指定された要素)をターゲットにしていること。
XPath引数が、XML Schemaで定義されているように、コレクションのchoiceをターゲットにしていないこと。
ターゲットになっているコレクションの親が、XML Schema内で注釈maintainDOM = "false"を使用して定義されていること。
XPath引数がコレクションを参照している場合、そのコレクションが、表外(REF記憶域)でも表内でもなく個別のOrdered Collection Tableとして格納されていること。
XPath引数がコレクションを参照している場合、そのコレクションがスカラー(maxOccurs > 1であるsimpleType)でないこと。
脚注の凡例
脚注1: 関数tableとXMLSequenceを使用するかわりに、よりわかりやすい標準のSQL/XML関数XMLTableを使用することもできます。