頻繁に問い合せるXMLデータの特定部分に着目できるよう当該XMLデータに対して索引を作成し、パフォーマンスを向上できます。この章では、これを実現するためのガイドラインを示します。スキーマに基づくか否かにかかわらず、また、使用されるXMLType
記憶域モデル(バイナリXML、非構造化、ハイブリッド、または構造化)に関係なく、XMLType
データに索引付けするための様々な方法について説明します。
この章の内容は次のとおりです。
注意: ここで示す実行計画は、説明のためのみに使用しています。ここで示す例を実際の環境で実行しても、実行計画が同一になるわけではありません。 |
関連項目:
|
表5-1は、索引付けに関連するいくつかのユーザー・タスクの参照先を示します。
表5-1 索引付けに関連するOracle XML DBタスク
操作の詳細 | 参照先 |
---|---|
非構造化 |
「非構造化XMLType表および列に対するファンクション索引の作成」 |
構造化 |
「構造化XMLType表および列に対するファンクション索引の作成」 |
構造化 |
「OCTとして格納されたコレクションでの、索引を使用した問合せのチューニング」 |
|
|
|
|
|
|
特定の表または列に対する |
|
XMLIndex索引名の変更 |
|
XMLIndex索引の削除 |
|
|
|
|
|
パス表の指定による、 |
|
|
|
パス表の |
|
パス表の |
|
パス表の |
|
パス表の |
|
|
|
|
|
|
|
|
「XMLIndexパスのサブセット化: 索引付けするパスの指定」 |
|
「XMLIndexパスのサブセット化: 索引付けするパスの指定」 |
Oracle XML DBリポジトリでの |
「Oracle XML DBリポジトリでのXMLIndexの使用」 |
|
「Oracle XML DBリポジトリでのXMLIndexの使用」 |
|
|
|
|
|
|
|
|
コストベース・オプティマイザに対する表または索引に関する統計の収集 |
|
Oracle Textの |
|
XMLデータの全文検索におけるOracle Textの |
|
Oracle Textの |
|
データベース索引では、表データに対するアクセスを高速化することにより、パフォーマンスが向上します。索引の使用は、更新が少ないオンライン・トランザクション処理(OLTP)環境に特に適しています。
表の1列または複数の列、またはファンクション式に対して索引を作成できます。XMLデータには独自のファイングレイン構造がありますが、その構造は、XMLデータが格納されるデータベース表の構造に必ずしも反映されるとはかぎりません。このような理由から、XMLデータに効果的に索引付けする方法は、他の大部分のデータベース・データに対する索引付けとは多少異なります。
構造化XML記憶域では、要素や属性などのXMLオブジェクトは、オブジェクト・リレーショナル列および表に対応しているため、これらの列および表に対してBツリー索引を作成する方法は、対応するXMLオブジェクトに効果的に索引付けする場合に最適です。この場合、記憶域モデルはXMLデータのファイングレイン構造を直接反映するため、構造化XMLデータの索引付けにおいて特別な問題は生じません。
非構造化記憶域およびハイブリッドXML記憶域では、標準的な索引(Bツリー、ビットマップ)を使用してデータベース列に索引付けすると、多くの場合、XML文書の特定部分にアクセスする際に問題が生じます。XML文書を含むXMLType
列がCLOB
インスタンスとして格納されると、その文書内の細部が列の索引にアクセスできなくなります。つまり、列の索引に関しては、文書全体が単独のユニットとして機能することになります。ハイブリッド記憶域では、XML文書の一部が分割され、オブジェクト・リレーショナル形式(構造化記憶域)で格納されますが、1つ以上のXMLフラグメントがCLOB
インスタンス(非構造化記憶域)として格納されます。このような場合は、通常、XML SchemaのcomplexType
または複合要素をCLOB
記憶域にマッピングします。これは、通常はフラグメント全体が1つの単位としてアクセスされるためです。標準的な索引の場合、索引付けの単位としても機能します。
XMLIndex
は通常のXML固有の索引により、XMLデータの内部構造に索引付けします。その主な目的の1つとして、XMLデータの非構造化記憶域およびハイブリッド記憶域、つまり、CLOB
記憶域によって課される、索引付けの制限を克服することがあげられます。これを行うには、文書のXMLタグに索引付けし、それをターゲットとするXPath式に基づいて文書のフラグメントを識別します。また、スカラー・ノードの値に対して索引付けすることで、単独の値または値の範囲に基づく高速参照も可能にします。さらに、索引付けする各ノードに対し、文書の階層情報(親と子、祖先と子孫、および兄弟)を記録します。
XMLIndex
に加え、XMLデータに対してはファンクション索引およびOracle Text索引も使用できます。Oracle Database 11gリリース1(11.1)以前のリリースでは、XMLデータにおいてCTXXPath
索引の使用が適していることもありました。
XPath式が単一のノードをターゲットとする多くのケースでは、アクセス・パフォーマンスを向上する方法として、ファンクション索引が効果的な場合もあります。XMLデータに対してこの種の索引を作成する場合は、SQL関数XMLQuery
、XMLExists
、XMLCast
、extract
、extractValue
、およびexistsNode
が特に有益です。問合せのWHERE
句のファンクション式がファンクション索引に一致すると、対応するデータへのアクセスは、より一般的なXMLIndex
索引よりも高速に行えることがあります。さらに、構造化記憶域では、SQL関数extractValue
に基づいて索引を定義すると、XPathリライトにより、基礎のオブジェクトに対して(Bツリー)索引が自動的に作成されることがあります。このような場合でも、XPathのターゲットは単一の要素または属性である必要があります。
要素や属性などのXMLノードにアクセスする以外にも、XMLテキスト・ノード内の特定の節に対して高速アクセスを提供する必要があることがあります。Oracle Text索引は全文文字列に対して索引付けすることで、この目的を達成します。Oracle TextのCONTEXT
索引では、XMLの全文検索を実行するためのSQL関数contains
を使用できます。構造化記憶域では、XPathリライトによりora:contains
XPath関数がcontains
SQL関数にリライトされることが多いため、このようなケースでもOracle Text索引が使用されます。全文索引は、特に、XML要素とテキストノード・コンテンツが混在する、文書中心のアプリケーションにおいて有用です。全文検索は、構造化XML検索と組み合せる(XPath式によって識別されるXML文書の一定部分に対して検索を限定する)ことによってさらに強力に、焦点を絞って行えるようになります。
XMLデータの索引付けに使用されていたもう1つの索引CTXXPath
は、Oracle Database 11gリリース1(11.1)で非推奨になりました。CTXXPath索引はXMLIndex
に置き換えられ、旧データベース・リリースでのみ使用されることになります。XMLフラグメントの抽出には使用されず、等価述語の事前フィルタとしてのみ機能します。事前フィルタリングを実行後、XPath式は関数として評価されます(つまり、XPathリライトの利点は活用されません)。
注意: CTXSYS.CTXXPath 索引は、Oracle Database 11gリリース1(11.1)で非推奨になりました。CTXXPath によって提供されていた機能は、XMLIndex で提供されるようになります。
|
1つのケースで複数の索引が該当する場合は、どの索引が使用されるでしょうか。パフォーマンスを最大化する索引(複数可)は、コストベースの最適化によって決定されます。Oracle Text索引はテキストにのみ適用されるため、XMLデータではテキスト・ノードを意味します。テキスト・ノードがターゲットとされ、対応するOracle Text索引が定義されている場合は、Oracle Text索引が使用されます。特定のコンテキストにおいて他の索引も適している場合は、これらも使用されます。ただし、索引が定義されており、特定の状況下において適しているように見えても、その索引が必ずしも使用されるとはかぎりません。コストベース・オプティマイザが費用効率を発揮できないと判断した索引は使用されません。
データがXML Schemaに基づくかどうかや、XMLType
記憶域が構造化、非構造化、またはバイナリXMLのどれであるかにかかわらず、XMLType
の表または列に対してファンクション索引を作成できます。ファンクション索引は、ターゲットの表または列の各行に指定された関数を評価し、索引に値を格納することで作成されます。ファンクション索引は、Bツリー索引またはビットマップ索引として作成できます。
構造化記憶域によって管理されていないXMLデータに対してファンクション索引が定義されている場合、XMLコンテンツに対して関数を起動して索引を作成し、結果に対して索引を作成します。(構造化記憶域のXMLデータに対してファンクション索引を作成した場合、必ずしもこのようになるとはかぎりません。詳細は、「構造化XMLType表および列に対するファンクション索引の作成」を参照してください。)
例5-1は、extractValue
SQL関数に基づいて索引を作成する方法を示します。この例では、XMLデータは非構造化(CLOB
)記憶域に格納されています。データはまず、標準的なデータベース・スキーマであるOE
の構造化記憶域のpurchaseorder
表から、CLOB
ベースのpo_clob
表にコピーされます。これらの表はいずれも、この章の例全体で使用されます。
例5-1 CLOB XMLTypeインスタンスに対するファンクション索引の作成
この例のCREATE INDEX
文は、Reference
要素のテキスト・ノードの値に対してファンクション索引を作成します。この索引では、テキスト・ノードの値に対する一意性制約が規定されます。
CREATE TABLE po_clob OF XMLType XMLTYPE STORE AS CLOB ELEMENT "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd#PurchaseOrder"; Table created. INSERT INTO po_clob SELECT OBJECT_VALUE FROM OE.purchaseorder; 132 rows created. CREATE UNIQUE INDEX po_fn_based_ix ON po_clob (extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference')); Index created. INSERT INTO po_clob VALUES (XMLType(bfilename('XMLDIR', 'EABEL-20021009123335791PDT.xml'), nls_charset_id('AL32UTF8'))); INSERT INTO po_clob * ERROR at line 1: ORA-00001: unique constraint (OE.PO_FN_BASED_IX) violated
コストベース・オプティマイザは、WHERE
句に含まれる関数が、索引の作成に使用される関数と同一である場合にのみ、ファンクション索引の使用を検討します。
これについては、例5-2の問合せと実行計画を参照してください。これらの問合せは、Reference
要素のテキスト・ノードに基づいて発注書をそれぞれ検索します。最初の問合せでは、existsNode
関数を使用して文書の位置を検索し、例5-1で作成された索引を使用していません。これに対して2番目の問合せでは、extractValue
関数を使用し、索引を使用しています。これは、extractValue
を使用して索引が作成されたためです。
例5-2 ファンクション索引は、一致する問合せでのみ使用
EXPLAIN PLAN FOR SELECT OBJECT_VALUE FROM po_clob WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="EABEL-20021009123335791PDT"') = 1; Explained. -- SET ECHO OFF PLAN_TABLE_OUTPUT ----------------------------------------------------------------------------- Plan hash value: 2803800196 ----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 42 | 84084 | 23 (27)| 00:00:01 | |* 1 | TABLE ACCESS FULL| PO_CLOB | 42 | 84084 | 23 (27)| 00:00:01 | ----------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(EXISTSNODE(SYS_MAKEXML('0BAD982DA615296BE040578CB00B1198', 3460,"PO_CLOB"."XMLDATA"),'/PurchaseOrder[Reference="EABEL-2002100912333 5791PDT"')=1) 15 rows selected. EXPLAIN PLAN FOR SELECT OBJECT_VALUE FROM po_clob WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference') = 'EABEL-20021009123335791PDT'; Explained. SET ECHO OFF PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------- Plan hash value: 2594805861 ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2002 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| PO_CLOB | 1 | 2002 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | PO_FN_BASED_IX | 1 | | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access(EXTRACTVALUE(SYS_MAKEXML('0BAD982DA615296BE040578CB00B1198',3460,"XMLDAT A"),'/PurchaseOrder/Reference')='EABEL-20021009123335791PDT') Note ----- - dynamic sampling used for this statement 19 rows selected.
構造化XMLType
記憶域を使用する場合、ファンクション索引を作成する際に注意が必要な点がいくつかあります。
関数がターゲットとする要素または属性は単一である必要があります。つまり、それらがXML文書で使用される回数は1回のみです。ファンクション索引はコレクションをターゲットにしないでください。「コレクションに対しては適用されないEXTRACTVALUEのXPathリライト」を参照してください。
索引付けされる関数がextractValue
である場合、Oracle XML DBは関数ベースのCREATE INDEX
文を関数ベースではない別のCREATE INDEX
文にリライトするため、XPath式の引数は使用しません。この場合、結果として作成される索引は、基礎となるオブジェクトに対して直接処理を行うBツリー索引になります。このBツリー索引は、指定されたファンクション索引のかわりに使用されます。「単一の要素または属性のEXTRACTVALUE索引に対するXPathリライト」を参照してください。
Oracle XML DBがCREATE INDEX
文をリライトできない場合、非構造化記憶域と同様にファンクション索引が作成されます。関数がextractValue
でない場合はもとより、関数がextractValue
であっても、場合によってはこのようなことが生じることがあります。
例5-3は、サンプル・データベース・スキーマOE
の構造化XMLType
表、purchaseorder
のCREATE INDEX
文を示します。この文は、extractValue
SQL関数を使用してファンクション索引を作成しており、単一のXML要素であるReference
をターゲットにしています。各発注書には、単独のReference
要素があります。
例5-3 単一の要素または属性のEXTRACTVALUEによるCREATE INDEX
CREATE INDEX po_fn_based_ix ON purchaseorder (extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference')); Index created.
Oracle XML DBは、このCREATE INDEX
文を例5-4の文にリライトします。作成される索引は、基礎となるオブジェクト・リレーショナル列に対するBツリー索引です。これは、USER_IND_COLUMNS
表の索引のCOLUMN_NAME
列で確認できます。基礎となるオブジェクト・リレーショナル列REFERENCE
が使用されていることがわかります。
SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME FROM USER_IND_COLUMNS
WHERE INDEX_NAME = 'PO_FN_BASED_IX' AND TABLE_NAME = 'PURCHASEORDER';
INDEX_NAME TABLE_NAME COLUMN_NAME
---------------- ---------------- ----------------------
PO_FN_BASED_IX PURCHASEORDER "XMLDATA"."REFERENCE"
1 row selected.
例5-4 単一の要素または属性に対するEXTRACTVALUE索引のXPathリライト
CREATE INDEX po_fn_based_ix ON purchaseorder p (p."XMLDATA"."REFERENCE"); Index created.
例5-3および例5-4の結果は同じです。同じ索引を2つの異なる方法で作成します。
SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME FROM USER_IND_COLUMNS
WHERE INDEX_NAME = 'PO_FN_BASED_IX' AND TABLE_NAME = 'PURCHASEORDER';
INDEX_NAME TABLE_NAME COLUMN_NAME
---------------- ---------------- ----------------------
PO_FN_BASED_IX PURCHASEORDER "XMLDATA"."REFERENCE"
1 row selected.
ファンクション索引は、ターゲットとされる要素または属性はコレクションではなく単一である必要があります。この項では、構造化記憶域を例にとって説明します。
コレクションがCLOB
インスタンスに格納されている場合は、コレクションのメンバーに直接アクセスできません。構造化記憶域では、コレクションはOrdered Collection TableまたはXMLType
インスタンスとして格納されるため、メンバーに直接アクセスできます。構造化記憶域モデルは、XMLデータのファイングレイン構造を直接反映するため、コレクション・メンバーをターゲットとする索引を作成できます。
しかし、XPath式によってコレクションをターゲットとする、extractValue
関数に基づく索引は作成できません。また、Oracle XML DBがCREATE INDEX
文をリライトし、基礎となるオブジェクトに対して必要となる索引を作成することもできません。
このような索引が必要な場合は、手動で作成する必要があります。そのためには、コレクションの管理に使用するSQLオブジェクトの構造を理解する必要があります。その情報に基づき、従来のオブジェクト・リレーショナルSQLを使用して、適切なSQLオブジェクト属性に対して必要となる(Bツリー)索引を直接作成できます。
この項では、XPathリライトを利用して適切な索引を作成することはできないことを示します。このような索引を手動で作成する方法の例は、「OCTとして格納されたコレクションでの、索引を使用した問合せのチューニング」を参照してください。
この項では、コレクションの繰返し属性に対してファンクション索引を意図的に作成し、どのような結果になるかを見ていきます。いくつかの方法で試行しますが、いずれも失敗に終わります。
Part
要素のId
属性に対し、索引を作成するとします。例5-5で示すように、索引を作成してみます。索引付けされる要素または属性は文書内で複数回出現するため、その要素または属性をターゲットとするXPath式のCREATE INDEX
操作は失敗します。これは、extractValue
SQL関数は、1行当たり1つの値しか返せないためです。このような場合、発注書でId
属性が複数回出現している可能性があります。その祖先要素であるLineItem
はコレクションであるためです。
例5-5 繰返し属性に対するファンクション索引の作成試行
CREATE INDEX po_fn_based_ix ON purchaseorder
(extractValue(OBJECT_VALUE, '/PurchaseOrder/LineItems/LineItem/Part/@Id'));
CREATE INDEX po_fn_based_ix ON purchaseorder
*
ERROR at line 1:
ORA-19025: EXTRACTVALUE returns value of only one node
この場合に索引を作成するには、例5-6で示すように、extractValue
関数ではなく、extract
関数とXMLType
メソッドgetStringVal()
の組合せを使用します。
例5-6 EXTRACTおよびgetStringVal()を使用したファンクション索引の作成
CREATE INDEX po_fn_based_ix ON purchaseorder (extract(OBJECT_VALUE, 'PurchaseOrder/LineItems/LineItem/Part/@Id').getStringVal()); Index created.
このCREATE INDEX
操作はファンクション索引の作成に成功しましたが、期待どおりの索引は得られませんでした。表の各行に対してSQL関数extract
およびXMLType
メソッドgetStringVal
を起動し、その行のROWIDに基づいて結果に索引を付けることで、索引が作成されます。
この手法の問題点は、extract
が複数のノードを戻すことです。extract
関数を使用した結果、一致するすべてのノードを含む単一のXMLType
フラグメントが戻されます。
注意: 通常は、extract SQL関数に基づく索引を作成しないようにしてください。この索引は、ほとんど実用的ではありません。 |
フラグメントを含むXMLType
インスタンスに対してgetStringVal()
メソッドを起動すると、そのフラグメント内のノードの連結が戻されます。したがって、索引付けされるのは3つのUPCコード(Id
属性)の連結であり、本来意図していた個々のUPCコードではありません。これを例5-7に示します。
例5-7 連結されたノードのファンクション索引
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') XML,
extract(OBJECT_VALUE, 'PurchaseOrder/LineItems/LineItem/Part/@Id').getStringVal() INDEX_VALUE
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
XML INDEX_VALUE
----------------------------------------------------------------- -----------------------------------
<LineItems> 71551500905837429140222715515011020
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="2">
<Description>The Unbearable Lightness Of Being</Description>
<Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="3">
<Description>Sisters</Description>
<Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
</LineItem>
</LineItems>
1 row selected.
この問題を解決するには、Ordered Collection Table(OCT)を有する構造化記憶域を使用し、索引付けされた各XMLノードを別々の行として強制的に格納するという方法があります。その後は、XPathリライトで生成されたSQLと同様に、オブジェクト・リレーショナルSQLを使用して、OCTに対して索引を直接作成できます。
つまり、XMLノードに対応するデータベース列を索引付けすることで、オブジェクト・リレーショナル(構造化記憶域)に格納されたXMLデータを効果的に索引付けできます。単一のextractValue
の場合、Oracle XML DBはこの操作を自動的に実行します。extractValue
関数に基づく索引を作成するための単純な構文を、XPath式の引数とともに使用するだけで、Oracle XML DBが残りのすべての操作を実行します。
この項の内容は次のとおりです。
構造化記憶域では、Bツリー索引を効果的に使用できます。基礎となるオブジェクトを直接ターゲット化することで、焦点をより明確に絞ることが可能になります。ただし、XML文書またはCLOB
インスタンスに格納されているフラグメントの詳細な構造(要素および属性)を指定する場合は、通常は効果を発揮しません。これは、XMLIndex
(非構造化およびハイブリッド記憶域)の特殊ドメインです。
XMLIndex
は一般的に、文書の一部に対してアクセスする場合に使用されるため、これらの部分を1つ以上のCLOB
インスタンスにパックします。それでも、文書内のこれらの部分に対して問い合せる必要が生じることもあります。ここではXMLIndex
が有効ですが、XPathリライトはこのような場合には効果はありません。
また、関連する文書構造とデータ型に対する特定の知識がなく、XML Schemaにxsd:any
要素が含まれている場合にも使用されます。これらの要素に対応するデータはCLOB
インスタンスに格納され、XMLIndex
を使用して、アクセス速度を高められます。
XMLのCLOB
格納に加え、XMLIndex
を使用してバイナリ形式のXMLType
データに索引付けすることもできます。
個々のXML要素または属性を表す特定のデータベース列に対して定義されるBツリー索引とは異なり、XMLIndex
索引は、通常の状態ではとても一般的なものです。つまり、索引付けにおいて特定のXPath式の使用、または不使用を細かく指定して焦点を絞らないかぎり、XMLIndex
による索引付けは、XMLデータで可能なすべてのXPath式に対して適用されます。
XMLIndex
索引は、SQL関数XMLQuery
、XMLTable
、XMLExists
、XMLCast
、extract
、extractValue
、およびexistsNode
に対して使用できます。他の索引付け方式に比べ、次のような利点があります。
XMLIndex
索引は、問合せのどの部分においても効果があります。つまり、WHERE
句での使用に限定されません。これは、XMLデータで使用される他の種類の索引では考えられません。
XMLIndex
はSELECT
リスト・データとFROM
リスト・データの両方に対するアクセスを高速化でき、特にXMLフラグメント抽出において有用です。ファンクション索引(および非推奨になったCTXXPath
索引)は、文書のフラグメントの抽出には使用できません。
問合せに使用されるXPath式に関する事前の知識は不要です。XMLIndex
は一般的なものです。ファンクション索引の場合とは異なります。事前の知識がある場合は、最も頻繁に問合せされるパスに合せてXMLIndex
の索引付けをチューニングすることで、パフォーマンスを高められます。
XMLIndex
索引は、XML Schemaに基づくデータ、またはスキーマに基づかないデータに対して使用できます。非構造化記憶域、ハイブリッド記憶域またはバイナリXML記憶域で使用できます。Bツリー索引は、オブジェクト・リレーショナル形式(構造化記憶域)で格納されるXML Schemaに基づくデータに対してのみ使用でき、CLOB
インスタンスに格納されるXML Schemaに基づくデータに対しては効果的ではありません。
XML Schemaに基づくデータのハイブリッド記憶域については、XMLIndex
は、CLOB
インスタンスに格納される文書のフラグメントをターゲットとするXPath式を処理できます。XPathリライトは、このようなケースには効果的ではありません。
XMLIndex
索引は、コレクション(文書内に複数回出現するノード)をターゲットとするXPath式による検索において使用できます。ファンクション索引の場合とは異なります。
XMLIndex
索引(索引の作成とメンテナンス)は、複数のデータベース処理により、並列的に実行できます。これは、ファンクション索引(および非推奨になったCTXXPATH
索引)の場合とは異なります。
バイナリXML記憶域のXMLIndex
索引はピース単位で更新できるため、DMLパフォーマンスを大幅に高められます。これは、XMLデータで使用される他の種類の索引では考えられません。
次の種類のXPath式は、XMLIndex
では索引付けされません。
ora:contains
以外のXPath関数の適用。特に、ユーザー定義されたXPath関数は索引付けされません。
child
、descendant
、およびattribute
以外の軸(parent
、ancestor
、following-sibling
、preceding-sibling
、following
、preceding
、およびancestor-or-self
の各軸)。
共用体演算子|
(垂直バー)を使用する式。
XMLIndex
はドメイン索引であり、XMLデータのドメイン向けに特化して設計されています。XMLIndexは論理索引であり、次の3つのコンポーネントがあります。
XMLIndex
は、パス表と、そのコンポーネントに対応する一連の(ローカルの)2次索引によって実装されます。これらはすべて、XMLIndex
索引が作成される実表の所有者によって所有されます。パス表では、XML文書で索引付けされる1つのノードに対して1行が使用されます。索引付けされたノードに対して、パス表には次のものが格納されます。
文書を格納する表に対応するROWID。
対応する文書のフラグメントへの高速アクセスを提供するロケータ。XML Schemaに基づくデータのバイナリXML記憶域については、データ型情報も格納します。
文書におけるノードの階層的な位置を記録するための順序キー。これは、図書目録やインターネット・プロトコルSNMPで使用されるような、デューイ10進分類キーのようなものです。このようなシステムでは、3.21.5
というキーは、文書のルート・ノードの3番目の子の21番目の子の5番目の子というノード位置を表します。
表5-2は、パス表に含まれる主な情報脚注1を示します。パス索引と順序索引は、パス表で2列ずつ使用します。PATHID
およびRID
列がパス索引、ORDER_KEY
とRID
列が順序索引を表します。2次索引は、PATHID
およびORDER_KEY
列に対して自動的に作成されます。
表5-2 XMLIndexのパス表
列 | データ型 | 説明 |
---|---|---|
|
|
ノードのXPathパスに対する一意の識別子です。 |
|
|
XMLデータを格納するために使用される表のROWIDです。 |
|
|
ノードの階層的な位置を識別するための、10進数の順序キーです。(ドキュメントの順序は保持されます。) |
|
|
フラグメント位置情報です。フラグメント抽出に使用されます。XML Schemaに基づくデータのバイナリXML記憶域では、データ型情報もここに格納されます。 |
|
|
属性ノードまたは単純な要素ノードのテキストです。 |
例5-8では、2つの発注書のパス表の内容を見ていきます。
例5-8 2つの発注書のパス表の内容
<PurchaseOrder> <Reference>SBELL-2002100912333601PDT</Reference> <Actions> <Action> <User>SVOLLMAN</User> </Action> </Actions> . . . </PurchaseOrder> <PurchaseOrder> <Reference>ABEL-20021127121040897PST</Reference> <Actions> <Action> <User>ZLOTKEY</User> </Action> <Action> <User>KING</User> </Action> </Actions> . . . </PurchaseOrder>
これらの発注書を格納するXMLType
表または列のXMLIndex
索引には、XML文書で索引付けされたノードに対し、1行ずつ使用するパス表が含まれます。仮に、XPath式に従ってノードに索引付けする際、システムによって次のPATHID
が割り当てられるとします。
PATHID | 索引付けされたXPath |
---|---|
1 |
/PurchaseOrder |
2 |
/PurchaseOrder/Reference |
3 |
/PurchaseOrder/Actions |
4 |
/PurchaseOrder/Actions/Action |
5 |
/PurchaseOrder/Actions/Action/User |
結果として作成されるパス表は、次のようになります(LOCATOR
列は示されません)。
PATHID | RID | ORDER_KEY | VALUE |
---|---|---|---|
1 |
R1 |
1 |
—— |
2 |
R1 |
1.1 |
SBELL-2002100912333601PDT |
3 |
R1 |
1.2 |
—— |
4 |
R1 |
1.2.1 |
—— |
5 |
R1 |
1.2.1.1 |
SVOLLMAN |
1 |
R2 |
1 |
—— |
2 |
R2 |
1.1 |
ABEL-20021127121040897PST |
3 |
R2 |
1.2 |
—— |
4 |
R2 |
1.2.1 |
—— |
5 |
R2 |
1.2.1.1 |
ZLOTKEY |
4 |
R2 |
1.2.2 |
—— |
5 |
R2 |
1.2.2.1 |
KING |
パス表の列に2次索引を作成した場合でも、パス表そのものは通常は無視できます。パス表には、それをDESCRIBE
したり、(2次)索引を作成したりする以外はアクセスできません。パス表に関する統計を明示的に収集する必要はありません。統計は、XMLIndex
索引、またはXMLIndex
索引が定義されている実表についてのみ収集します。統計が収集されると、それはパス表と2次索引に透過的に保持されます。
VALUE
列の2次索引は、一致する文字列に関する述語を有するWHERE
句のXPath式で使用されます。次に例を示します。
/PurchaseOrder[Reference/text() = "SBELL-2002100912333601PDT"]
VALUE
列は、単一の要素ノード(子なし)または属性ノードの有効テキスト値を格納します。要素に対しては、要素のすべてのテキスト・ノードを連結することで取得されます。索引付けの際、コメントおよび処理命令は無視されます。
VALUE
列のサイズは、VARCHAR2(4000)
に固定されています。索引の作成または更新時における超過分(4000バイトを超える分)は切り捨てられますが、当該行のLOCATOR
値はフラグ付けされるため、必要に応じて完全な値を実表から取得することは可能です。
VALUE
列に対する4000バイトの上限に加え、当該列に対して作成される2次索引のキーのサイズにも制限があります。これは、Bツリー索引とファンクション索引にも該当します。XMLIndex
の制限ではありません。索引キーのサイズの限界は、データベースのブロック・サイズの関数です。VALUE
に対してどの程度の索引付けがなされるかは、この制限値によって決定します。
つまり、有効テキスト値の最初の4000バイトのみがVALUE
列に格納され、VALUE
列の最初のNバイトに対してのみ索引が作成されるということです。ここでNとは、索引キーのサイズの制限を表します(N < 4000)。索引キーのサイズの制限が課されることにより、VALUE
列の索引は、有効テキスト値の事前フィルタとしてのみ機能します。
たとえば、データベースのブロック・サイズにより、VALUE
列の索引を800バイト以内に抑え、有効テキスト値のうち最初の800バイト分のみを索引付けするとします。有効テキスト値の最初の800バイト分に対してXMLIndexを
使用してテストを実行し、そのテキスト接頭辞が問合せ値に一致した場合のみ、残りの有効テキスト値がテストされます。
VALUE
列の2次索引は、substr
SQL関数(サブストリング等価性)です。この関数を使用して、テキスト接頭辞に対するテストを実行するためです。このファンクション索引は、VALUE
列に対するXMLIndex
の実装の一環として自動的に作成されます。
たとえば、問合せのWHERE
句のXPath式/PurchaseOrder[Reference/text() = :1]
は、実質的に、次のようなテストにリライトされることがあります。
substr(VALUE, 1 800) = substr(:1, 1, 800) AND VALUE = :1;
この結合は2つの部分から構成され、左から右に向かって処理されます。1つ目のテストでは、substr
関数の索引を事前フィルタとして使用し、冒頭800バイトがバインド変数:1
の冒頭800バイトに一致しないテキストを削除します。
索引は、1つ目のテストでのみ使用されます。VALUE
列の完全な値は索引付けされません。1つ目のテストで事前フィルタリングを実行した後、2つ目のテストで有効テキスト値全体をチェックします。つまり、VALUE
列の完全な値と、:1
の値の等価性を確認します。このチェックでは索引は使用されません。
テキストの冒頭800バイトのみが索引付けされる場合でも、問合せパフォーマンスでは、最大4000バイトをVALUE
列に格納することが重要になります。これにより、CLOB
インスタンスのXML文書内の深い部分からデータを抽出することなく、データに迅速かつ直接的にアクセスできるようになるからです。有効テキスト値が4000バイトを超える場合は、WHERE
句結合の2つ目のテストにおいて、実表データにアクセスする必要があります。
VALUE
列に対する4000バイト上限も、索引キーのサイズも、問合せ結果には何の影響も与えません。これらはパフォーマンスにのみ影響を与えます。
XMLIndex
索引を作成する際、VALUE
列に対して2次索引を指定しない場合、VALUE
列に対してデフォルトの2次索引が作成されます。このデフォルト索引には、デフォルトのプロパティがあります。具体的には、これはテキスト(文字列値)データでのみ使用される索引です。
ただし、異なる種類のVALUE
索引を作成できます。たとえば、数値の索引が問合せの大半に適している場合は、数値の索引を作成できます。VALUE
列に対し、複数の2次索引を作成できます。特定の種類の索引は、それが適切な場合にのみ使用されます。たとえば、数値の索引は、VALUE
列が数値である場合にのみ使用されます。その他の値の場合は無視されます。パス表の列の2次索引は、その他の2次索引と同様に扱われます。つまり、これらの索引は変更、削除、不使用としてマーキングするなどが可能です。
関連項目:
|
標準的なデータベース索引に関する情報は、静的なパブリック・ビューUSER_INDEXES
、ALL_INDEXES
、およびDBA_INDEXES
にあります。XMLIndex
索引に関する同様の情報も、静的なパブリック・ビューUSER_XML_INDEXES
、ALL_XML_INDEXES
、およびDBA_XML_INDEXES
にあります。表5-3は、これらの各ビューの列について説明します。
表5-3 XMLIndexの静的なパブリック・ビュー
列名 | 型 | 説明 |
---|---|---|
|
|
索引の所有者です。 |
|
|
|
|
|
索引が定義されている実表の所有者です。 |
|
|
索引が定義されている実表の名前です。 |
|
|
|
|
|
索引固有のパラメータです。これには、パスのサブセット化を定義する一連のXPathパスと、同期化されるスケジューラ・ジョブの名前が含まれます。 |
|
|
非同期索引の更新の仕様です。「XMLIndex索引の非同期(遅延)メンテナンス」を参照してください。 |
|
|
最後に行われた索引の同期以降の、実表のDML操作を記録する表の名前です。「XMLIndex索引の非同期(遅延)メンテナンス」を参照してください。 |
例5-9に示すように、索引タイプをXDB.XMLIndex
と宣言して、XMLIndex
索引を作成します。
例5-9 XMLType非構造化記憶域でのXMLIndex索引の作成
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLIndex;
Index created.
これにより、XMLType
のpo_clob
表に、po_xmlindex_ix
という名前のXMLIndex
索引が作成されます。
注意: XMLType の表や列はパーティション化できますが、そのような表や列にはXMLIndex 索引を作成できません。 |
ハイブリッドXMLType
記憶域のCLOB
部分、つまりオブジェクト・リレーショナル記憶域に埋め込まれているCLOB
データにはXMLIndex
索引を作成できます。例5-10に、これを示します。ここでは、例5-10に示されているように、使用されるXML SchemaがLineItems
要素をCLOB
にマップすると想定しています。
例5-10 XMLTypeハイブリッド記憶域でのXMLIndex索引の作成
CREATE INDEX po_xmlindex_hybrid_ix ON li_clob (extract(OBJECT_VALUE, '/PurchaseOrder/LineItems')) INDEXTYPE IS XDB.XMLIndex;
例5-11 LineItemsをCLOBにマップするXML Schema断片
<xs:element name="LineItems" type="LineItemsType" xdb:SQLName="LINEITEMS" xdb:SQLType="CLOB"/>
例5-12に示すように、特定のXMLType
表(または列)のXMLIndex
索引の名前を取得できます。また、適宜DBA_INDEXES
またはALL_INDEXES
からINDEX_NAME
を選択することも可能です。
例5-12 特定の表にあるXMLIndex索引の名前の取得
SELECT INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME = 'PO_CLOB' AND ITYP_NAME = 'XMLINDEX'; INDEX_NAME --------------- PO_XMLINDEX_IX 1 row selected.
例5-13に示すように、XMLIndex
索引は、他の索引と同様に名前変更または削除できます。この名前変更により、XMLIndex
索引の名前のみが変更されます。この処理ではパス表の名前は変更されません。パス表は、個別に名前を変更できます。
例5-13 XMLIndex索引の名前変更と削除
ALTER INDEX po_xmlindex_ix RENAME TO new_name_ix;
Index altered.
DROP INDEX new_name_ix;
Index dropped.
同様に、REBUILD
などのALTER INDEX
オプションを使用し、他の索引プロパティも変更できます。この点においては、XMLIndex
も他の索引タイプと同じです。
CREATE INDEX
文のPARAMETERS
句を使用して、パス表に名前を付けることができます。例5-14では、パス表に"my_path_table"という名前を付けます。
5-14 XMLIndex索引のパス表への名前付け
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLIndex
PARAMETERS ('PATH TABLE my_path_table');
この方法でパス表に名前を付けなかった場合、名前はCREATE INDEX
に与えた索引名に基づき、システムによって自動的に生成されます。例5-15に、例5-9で作成した索引を使用した例を示します。
例5-15 XMLIndexパス表のシステム生成名の決定
SELECT PATH_TABLE_NAME FROM USER_XML_INDEXES WHERE TABLE_NAME = 'PO_CLOB' AND INDEX_NAME = 'PO_XMLINDEX_IX'; PATH_TABLE_NAME ------------------------------ SYS72060_PO_XMLINDE_PATH_TABLE 1 row selected.
デフォルトでは、XMLIndex
パス表と2次索引の記憶域オプションは、XMLIndex
索引が作成された実表の記憶域プロパティから生成されます。例5-16で示すように、索引の作成時にPARAMETERS
句を使用すると、異なる記憶域オプションを指定できます。CREATE INDEX
(およびALTER INDEX
)のPARAMETERS
句は、一重引用符('
)で囲む必要があります。
例5-16 XMLIndex索引の作成時における記憶域オプションの指定
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLIndex PARAMETERS ('PATH TABLE po_path_table (PCTFREE 5 PCTUSED 90 INITRANS 5 STORAGE (INITIAL 1k NEXT 2k MINEXTENTS 3 BUFFER_POOL KEEP) NOLOGGING ENABLE ROW MOVEMENT PARALLEL 3) PATH ID INDEX po_path_id_ix (LOGGING PCTFREE 1 INITRANS 3) ORDER KEY INDEX po_order_key_ix (LOGGING PCTFREE 1 INITRANS 3) VALUE INDEX po_value_ix (LOGGING PCTFREE 1 INITRANS 3)'); Index created.
XMLIndex
は論理的なドメイン索引であり、物理索引ではないため、すべての物理属性はゼロ(0
)またはNULL
になります。
例5-16では、パス表に対する記憶域オプションの指定に加え、2次索引にも名前を付けています。索引は、指定されているVALUE
列に対して作成されます。指定されていない場合、索引は作成されません。
パス表の名前と同様、パス表の列の2次索引の名前は、PARAMETERS
句で指定しないかぎり、索引名をベースとして自動的に生成されます。例5-17にこれを示します。これらの名前をパブリック・ビューUSER_IND_COLUMNS
で決定する方法も示します。また、RID
列も含め、パス索引と順序索引はそれぞれ2列ずつ使用することも示します。さらに、デフォルトではVALUE
索引は作成されないことに注意してください。
例5-17 XMLIndex索引の2次索引の名前付け
SELECT INDEX_NAME, COLUMN_NAME, COLUMN_POSITION FROM USER_IND_COLUMNS WHERE TABLE_NAME IN (SELECT PATH_TABLE_NAME FROM USER_XML_INDEXES WHERE INDEX_NAME = 'PO_XMLINDEX_IX') ORDER BY INDEX_NAME, COLUMN_NAME; INDEX_NAME COLUMN_NAME COLUMN_POSITION ------------------------------ ------------ --------------- SYS73321_PO_XMLINDE_ORDKEY_IX ORDER_KEY 2 SYS73321_PO_XMLINDE_ORDKEY_IX RID 1 SYS73321_PO_XMLINDE_PATHID_IX PATHID 1 SYS73321_PO_XMLINDE_PATHID_IX RID 2 4 rows selected.
XMLIndex
のALTER INDEX
文のRENAME
句は、XMLIndex
そのものに対してのみ適用されます。パス表および2次索引の名前を変更するには、これらのオブジェクトの名前を決定し、適切なALTER INDEX
文を直接使用する必要があります。同様に、2次索引の物理プロパティを取得したり、他のなんらかの方法で変更を加えたりする場合は、例5-17の方法に従って2次索引の名前を取得する必要があります。
ALTER INDEX
を使用すると、1次索引または2次索引の索引パラメータを修正できます。便宜上、パスID、順序キー、または値索引のプロパティを変更する代替策として、親XMLIndex
索引に対してALTER INDEX
を使用し、PARAMETERS
句に新しいプロパティを与える方法があります。
この項では、例5-16で作成したXMLIndex
に対し、2次索引を追加で作成します。
XMLIndex
索引のパス表のVALUE
列に対し、2次索引をいくつでも追加で作成できます。ファンクション索引やOracle Text索引など、様々な種類が可能です。
問合せの処理時に、指定の索引が指定の要素に対して使用されるかどうかは、その索引が当該値に対して適切であるかどうかや、その索引の使用が費用効率に優れているかどうかによって決まります。
例5-18では、substr
SQL関数を使用して、パス表のVALUE
列にファンクション索引を作成します。問合せにおいて、XML要素のテキスト・ノードに対してsubstr
がよく使用される場合は便利な方法です。
例5-18 パス表のVALUE列に対するファンクション索引の作成
CREATE INDEX fn_based_ix ON po_path_table (substr(VALUE, 1, 100)); Index created.
テキスト・ノードが数値を表す要素が多数ある場合、VALUE
列に対して数値索引を作成すると有効です。ただし、例5-18と同じような方法で数値索引を直接作成すると、要素値のいずれかが数値ではない場合にORA-01722エラー(無効な数値)が発生します。これを例5-19に示します。
例5-19 パス表のVALUE列に対する、数値索引の直接作成
CREATE INDEX direct_num_ix ON po_path_table (to_number(VALUE)); CREATE INDEX direct_num_ix ON po_path_table (to_number(VALUE)) * ERROR at line 1: ORA-01722: invalid number
ここで必要となるのは、数値の要素に対して使用されるが、数値を持たない要素に対しては無視される索引です。特に、DBMS_XMLINDEX
パッケージのcreateNumberIndex
プロシージャは、この目的でのみ存在するものです。このプロシージャに、データベース・スキーマの名前、XMLIndex
索引、および作成される数値索引を渡します。数値索引の作成は、例5-20に示します。
例5-20 createNumberIndexプロシージャによる、VALUE列に対する数値索引の作成
CALL DBMS_XMLINDEX.createNumberIndex('OE', 'PO_XMLINDEX_IX', 'API_NUM_IX');
このような索引は数値を持たない要素を無視するよう設計されているため、この索引が数値を持たない要素を検出することはありません。非数値要素がある場合に、なんらかの理由によりXMLIndex
索引が問合せで使用されなければ、ORA-01722
エラーが発生します。ただし、索引が使用されると非数値データは無視されるため、エラーは発生しません。ここでも、索引の使用により結果セットが変わることはありません。結果はまったく同じですが、索引を使用すると、誤ったデータの生成を防ぐことはできます。
日付値の索引の作成は、数値索引の作成と似ています。この場合は、DBMS_XMLINDEX.createDateIndex
プロシージャを使用します。例5-21にこれを示します。
例5-21 createDateIndexプロシージャによる、VALUE列に対する日付索引の作成
CALL DBMS_XMLINDEX.createDateIndex('OE', 'PO_XMLINDEX_IX', 'API_DATE_IX',
'dateTime');
例5-22では、Oracle TextのCONTEXT
索引をVALUE
列に作成します。これは、XML要素のテキスト値に対する全文問合せにおいて便利です。XPath関数ora:contains
を使用するXPath述語は、VALUE
列のcontains
SQL関数の使用に合せてリライトされます。CONTEXT
索引がVALUE
列に対して定義されている場合、述語の評価時に使用されます。Oracle Text索引は、他のすべてのVALUE
列の索引に依存しません。
例5-22 パス表のVALUE列に対するOracle Text CONTEXT索引の作成
CREATE INDEX po_otext_ix ON po_path_table (VALUE)
INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS('TRANSACTIONAL');
Index created.
例5-23の問合せは、XMLIndex
索引のパス表に対して作成されたすべての2次索引を示します。作成された索引は、明確に太字で示されます。特に注意する必要があるのは、VALUE
列に作成されたファンクション索引などは、この例のように表示されない点です。これらの索引の列名は、SYS_NC00006$
などのシステム生成名になります。そのため、WHERE
句でCOLUMN_NAME='VALUE'
を使用して問合せを実行しても、これらの列を見ることはできません。
例5-23 XMLIndexのパス表上にある、すべての2次索引の表
SELECT c.INDEX_NAME, c.COLUMN_NAME, c.COLUMN_POSITION, e.COLUMN_EXPRESSION FROM USER_IND_COLUMNS c LEFT OUTER JOIN USER_IND_EXPRESSIONS e ON (c.INDEX_NAME = e.INDEX_NAME) WHERE c.TABLE_NAME IN (SELECT PATH_TABLE_NAME FROM USER_XML_INDEXES WHERE INDEX_NAME = 'PO_XMLINDEX_IX') ORDER BY c.INDEX_NAME, c.COLUMN_NAME; INDEX_NAME COLUMN_NAME COLUMN_POSITION COLUMN_EXPRESSION -------------------- ------------ --------------- ---------------------- API_DATE_IX SYS_NC00008$ 1 SYS_EXTRACT_UTC(SYS_XMLCONV("V ALUE",3,8,0,0,181)) API_NUM_IX SYS_NC00007$ 1 TO_BINARY_DOUBLE("VALUE") FN_BASED_IX SYS_NC00006$ 1 SUBSTR("VALUE",1,100) PO_ORDER_KEY_IX ORDER_KEY 2 PO_ORDER_KEY_IX RID 1 PO_OTEXT_IX VALUE 1 PO_PATH_ID_IX PATHID 1 PO_PATH_ID_IX RID 2 PO_VALUE_IX VALUE 1 9 rows selected.
関連項目:
|
指定のXMLIndex
索引を使用できるかどうかは、問合せのコンパイル時に決定されます。つまり、索引に対する問合せにその問合せをリライトできるかどうかによって決まります。問合せのXPath式が、索引付けに使用するよう指定されたパスのサブセットであることをコンパイル時に断定できない場合、XMLIndex
索引は使用されません。たとえば、索引付けの際にパス/PurchaseOrder/LineItems//*
が含まれる場合、/PurchaseOrder/LineItems/LineItem/Description
を含む問合せでは索引を使用できますが、//Description
を含む問合せは索引を使用できません。後者は、/PurchaseOrder/LineItems
の子ではない潜在的なDescription
要素と一致し、そのDescription
要素がデータに出現するかどうかはコンパイル時に判断できません。
特定のXMLIndex
索引が問合せの解決に使用されたかどうかを把握するには、問合せの実行計画を検証します。索引が使用される場合、そのパス表、順序キー、またはパスIDが実行計画において参照されます。実行計画は、ドメイン索引が使用されていることを直接的に示したり、XMLIndex
索引を名前で参照したりすることはありません。
関連項目:
|
例5-24は、例5-14で作成したXMLIndex
索引が特定の問合せで使用される様子を示します。
例5-24 XMLIndexの使用を確認するための、実行計画の検証
ここで示す実行計画のMY_PATH_TABLE
への参照は、XMLIndex
索引(例5-14で作成)が問合せで使用されることを示します。同様に、LOCATOR
、ORDER_KEY
、およびPATHID
の各列への参照も、同じことを示します。
SET AUTOTRACE ON EXPLAIN SELECT XMLQuery('/PurchaseOrder/Requestor' PASSING OBJECT_VALUE RETURNING CONTENT) FROM po_clob WHERE XMLExists('/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]' PASSING OBJECT_VALUE); XMLQUERY('/PURCHASEORDER/REQUESTOR'PASSINGOBJECT_VALUERETURNINGCONTENT) ----------------------------------------------------------------------- <Requestor>Sarah J. Bell</Requestor> 1 row selected. Execution Plan . . . ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 24 | 15 (7)| 00:00:01 | | 1 | SORT GROUP BY | | 1 | 3524 | | | |* 2 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 2 | 7048 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | SYS55148_PO_XMLINDE_PATHID_IX | 6 | | 1 (0)| 00:00:01 | | 4 | NESTED LOOPS | | 1 | 24 | 15 (7)| 00:00:01 | | 5 | VIEW | VW_SQ_1 | 1 | 12 | 13 (0)| 00:00:01 | | 6 | HASH UNIQUE | | 1 | 5046 | | | | 7 | NESTED LOOPS | | | | | | | 8 | NESTED LOOPS | | 1 | 5046 | 13 (0)| 00:00:01 | |* 9 | TABLE ACCESS BY INDEX ROWID| MY_PATH_TABLE | 1 | 3524 | 11 (0)| 00:00:01 | |* 10 | INDEX RANGE SCAN | SYS55148_PO_XMLINDE_PATHID_IX | 1 | | 2 (0)| 00:00:01 | |* 11 | INDEX RANGE SCAN | SYS55148_PO_XMLINDE_PATHID_IX | 6 | | 1 (0)| 00:00:01 | |* 12 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 1522 | 2 (0)| 00:00:01 | | 13 | TABLE ACCESS BY USER ROWID | PO_CLOB | 1 | 12 | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(SYS_XMLI_LOC_ISNODE("SYS_P0"."LOCATOR")=1) 3 - access("SYS_P0"."PATHID"=HEXTORAW('74C39DFE') AND "SYS_P0"."RID"=:B1) 9 - filter("SYS_P5"."PATHID"=HEXTORAW('6F7C') AND SYS_XMLI_LOC_ISNODE("SYS_P5"."LOCATOR")=1) 10 - access("SYS_P5"."VALUE"='SBELL-2002100912333601PDT') 11 - access("SYS_P2"."PATHID"=HEXTORAW('093CA37E') AND "SYS_P5"."RID"="SYS_P2"."RID") 12 - filter(SYS_XMLI_LOC_ISNODE("SYS_P2"."LOCATOR")=1 AND "SYS_P2"."ORDER_KEY"<"SYS_P5"."ORDER_KEY" AND "SYS_P5"."ORDER_KEY"<SYS_ORDERKEY_MAXCHILD("SYS_P2"."ORDER_KEY") AND SYS_ORDERKEY_DEPTH("SYS_P2"."ORDER_KEY")+1=SYS_ORDERKEY_DEPTH("SYS_P5"."ORDER_KEY")) . . .
例5-25に示すように、このような実行計画のパス表の名前から、XMLIndex
索引の名前を取得できます。(これは、例5-15の問合せとはほぼ反対のケースです。)
例5-25 パス表名からの、XMLIndex索引名の取得
SELECT INDEX_NAME FROM USER_XML_INDEXES WHERE PATH_TABLE_NAME = 'MY_PATH_TABLE'; INDEX_NAME ------------------------------ PO_XMLINDEX_IX 1 row selected.
XMLIndex
は、SELECT
リスト、FROM
リスト、および問合せのWHERE句
のXPath式で使用でき、SQL関数XMLQuery
、XMLTable
、XMLExists
、XMLCast
、extractValue
、existsNode
、およびextract
において有用です。ファンクション索引(および非推奨になったCTXXPath
索引)とは異なり、XMLIndex
索引は、文書からXMLフラグメントを抽出する際に使用できます。例5-26に、これを示します。
例5-26 XMLIndexを使用したXMLフラグメントの抽出
SET AUTOTRACE ON EXPLAIN SELECT li.description, li.itemno FROM po_clob, XMLTable('/PurchaseOrder/LineItems/LineItem' PASSING OBJECT_VALUE COLUMNS "DESCRIPTION" VARCHAR(40) PATH '/LineItem/Description', "ITEMNO" INTEGER PATH '/LineItem/@ItemNumber') li WHERE XMLExists('/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]' PASSING OBJECT_VALUE); DESCRIPTION ITEMNO ---------------------------------------- ---------- A Night to Remember 1 The Unbearable Lightness Of Being 2 Sisters 3 3 rows selected.
この問合せの実行計画は、パス表を参照することにより、XMLIndex
が使用されることを示します。また、内部SQL関数sys_orderkey_depth
が使用されることも示します。詳細は、「XMLIndex使用時のガイドライン」を参照してください。
Execution Plan . . . ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost(%CPU)| Time | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1546 | 8 (13)| 00:00:01 | |* 1 | FILTER | | | | | | |* 2 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 3524 | 2 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | SYS63727_PO_XMLINDE_PATHID_IX | 6 | | 1 (0)| 00:00:01 | |* 4 | FILTER | | | | | | |* 5 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 3524 | 2 (0)| 00:00:01 | |* 6 | INDEX RANGE SCAN | SYS63727_PO_XMLINDE_PATHID_IX | 1 | | 1 (0)| 00:00:01 | . . . |* 14 | TABLE ACCESS BY INDEX ROWID| MY_PATH_TABLE | 1 | 3524 | 2 (0)| 00:00:01 | |* 15 | INDEX RANGE SCAN | SYS63727_PO_XMLINDE_VALUE_IX | 1 | | 1 (0)| 00:00:01 | |* 16 | INDEX RANGE SCAN | SYS63727_PO_XMLINDE_ORDKEY_IX | 1 | | 1 (0)| 00:00:01 | |* 17 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 1522 | 2 (0)| 00:00:01 | | 18 | TABLE ACCESS BY USER ROWID | PO_CLOB | 1 | 12 | 1 (0)| 00:00:01 | |* 19 | INDEX RANGE SCAN | SYS63727_PO_XMLINDE_PATHID_IX | 6 | | 1 (0)| 00:00:01 | |* 20 | TABLE ACCESS BY INDEX ROWID | MY_PATH_TABLE | 1 | 1522 | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(:B1<SYS_ORDERKEY_MAXCHILD(:B2)) 2 - filter("SYS_P3"."ORDER_KEY">:B1 AND SYS_XMLI_LOC_ISNODE("SYS_P3"."LOCATOR")=1 AND "SYS_P3"."ORDER_KEY"<SYS_ORDERKEY_MAXCHILD(:B2) AND SYS_ORDERKEY_DEPTH("SYS_P3"."ORDER_KEY")= SYS_ORDERKEY_DEPTH(:B3)+1) 3 - access("SYS_P3"."PATHID"=HEXTORAW('54393E4C') AND "SYS_P3"."RID"=:B1) 4 - filter(:B1<SYS_ORDERKEY_MAXCHILD(:B2)) 5 - filter("SYS_P6"."ORDER_KEY">:B1 AND SYS_XMLI_LOC_ISNODE("SYS_P6"."LOCATOR")=1 AND "SYS_P6"."ORDER_KEY"<SYS_ORDERKEY_MAXCHILD(:B2) AND SYS_ORDERKEY_DEPTH("SYS_P6"."ORDER_KEY")= SYS_ORDERKEY_DEPTH(:B3)+1) 6 - access("SYS_P6"."PATHID"=HEXTORAW('7DE452AA') AND "SYS_P6"."RID"=:B1) filter(SYS_PATHID_IS_NMSPC("SYS_P6"."PATHID")=0) 14 - filter("SYS_P11"."PATHID"=HEXTORAW('6F7C') AND SYS_XMLI_LOC_ISNODE("SYS_P11"."LOCATOR")=1) 15 - access("SYS_P11"."VALUE"='SBELL-2002100912333601PDT') 16 - access("SYS_P11"."RID"="SYS_P8"."RID" AND "SYS_P8"."ORDER_KEY"<"SYS_P11"."ORDER_KEY") 17 - filter("SYS_P8"."PATHID"=HEXTORAW('093CA37E') AND SYS_XMLI_LOC_ISNODE("SYS_P8"."LOCATOR")=1) 19 - access("SYS_P0"."PATHID"=HEXTORAW('7676FDEA') AND "SYS_P0"."RID"="PO_CLOB".ROWID) 20 - filter(SYS_XMLI_LOC_ISNODE("SYS_P0"."LOCATOR")=1) . . .
XMLIndex
索引の使用を無効にするには、次のいずれかの方法を使用できます。
オプティマイザ・ヒント/*+ NO_XMLINDEX_REWRITE */
を使用
オプティマイザ・ヒント/*+ NO_XMLINDEX_REWRITE_IN_SELECT */
を使用
オプティマイザ・ヒント/*+ NO_XML_QUERY_REWRITE */
を使用
いずれの方法でも、すべてのXMLIndex
索引の使用が無効になります。NO_XML_QUERY_REWRITE
は、XMLIndex
の使用を無効にする他に、XPathリライトもすべて無効にします(XMLIndex
はXPathリライトの一部です)。
ヒントNO_XMLINDEX_REWRITE_IN_SELECT
は、SELECT
リスト内のXPath式についてだけXMLIndex
インデックスの使用を無効にします。問合せの他の部分のXPath式ではまだWHERE
句またはFROM
句などのXMLIndex
インデックスを使用できます。このヒントは、SELECT
リストのXPath式のストリーミング評価の方がXMLIndex
よりパフォーマンスが優れている、バイナリXMLに格納されたXMLデータの場合に特に便利です。
例5-27に、これらのオプティマイザ・ヒントの使用方法を示します。
例5-27 オプティマイザ・ヒントを使用したXMLIndexの無効化
SELECT /*+ NO_XMLINDEX_REWRITE */ count(*) FROM po_clob WHERE existsNode(OBJECT_VALUE, '/*') = 1; SELECT /*+ NO_XMLINDEX_REWRITE_IN_SELECT */ extractValue(li.OBJECT_VALUE, '/LineItem/Description') FROM po_clob p, table(XMLSequence(extract(p. OBJECT_VALUE, '/PurchaseOrder/LineItems/LineItem'))) li; SELECT /*+ NO_XMLINDEX_REWRITE_IN_SELECT */ li.description FROM po_clob p, XMLTable('/PurchaseOrder/LineItems/LineItem' PASSING OBJECT_VALUE COLUMNS "DESCRIPTION" VARCHAR(40) PATH '/LineItem/Description') li; SELECT /*+ NO_XML_QUERY_REWRITE */ count(*) FROM po_clob WHERE existsNode(OBJECT_VALUE, '/*') = 1;
ヒントNO_XMLINDEX_REWRITE_IN_SELECT
を使用する各問合せで、SELECT
リストのXPath式はXMLIndex
を使用しませんが、FROM
句のXPath式、/PurchaseOrder/LineItems/LineItem
はXMLIndex
を使用することがあります。関数XMLTable
を使用する問合せでは、列li.description
に対応するXPath式はSELECT
リストにテキストとして出現しませんが、XPathリライトのため、出現しているかのように扱われます。つまり、XPathリライトはXPath式を、SELECT
リストに存在しているかのように扱います。
注意: NO_INDEX オプティマイザ・ヒントは、XMLIndex には適用されません。 |
XMLIndex
には、とても一般的であるという利点があります。索引付けするXPathの位置を指定する必要はありません。問合せされるXPath式に関する事前の知識も必要ありません。デフォルトでは、XMLIndex
は、XMLデータのXPathで可能な位置であれば、どこでも索引付けできます。
ただし、問い合せる可能性の高いXPath式を認識している場合は、XMLIndex
の索引付けの焦点を絞り、パフォーマンスを高めることもできます。不要な索引が少ないほど、索引付けに必要な領域も削減されるため、DML操作中の索引のメンテナンスが向上します。索引付けされたノードの数が少ないほどDDLのパフォーマンスが向上し、パス表が小さいほど問合せのパフォーマンスも向上します。
索引付けされるXMLフラグメントに対応する一連のXPath式(パス)をプルーニングし、可能なすべてのパスのサブセットを指定することで、索引付けの焦点を絞れます。これを行うには、他に2通りの方法があります。
除外: 可能なすべてのXPath式を含めるというデフォルト動作を実行した後に、索引付けに不要なものを除外します。
包含: 索引付けに使用する空白のXPath式の包含セットにパスを追加します。
CREATE INDEX
を使用してXMLIndex
索引を作成するとき、またはALTER INDEX
を使用して索引を修正するときに、パスのサブセット化を指定できます。いずれの場合でも、文のPARAMETERS
句のPATHS
パラメータで、サブセット化情報を提供します。除外の場合は、キーワードEXCLUDE
を使用します。包含の場合は、ALTER INDEX
のときはキーワードINCLUDE
を使用し、CREATE INDEX
のときはキーワードを使用しません(含めるパスをリストします)。また、PATHS
パラメータによってターゲット化されるノードに対し、名前空間マッピングも指定できます。
ALTER INDEX
の場合、キーワードINCLUDE
またはEXCLUDE
の後にキーワードADD
またはREMOVE
を付加すると、キーワードの後に続くパスのリストを包含リストや除外リストに追加するか削除するかを指定できます。たとえば、この文では、索引付けから除外するパスのリストにパス/PurchaseOrder/Reference
を追加します。
ALTER INDEX po_xmlindex_ix REBUILD
PARAMETERS ('PATHS (EXCLUDE ADD (/PurchaseOrder/Reference))');
XMLIndex
索引に可能なパスをすべて含めるように当該の索引を修正する場合は、パスの明示的なリストのかわりにキーワードALL
を使用できます。つまり、EXCLUDE REMOVE (ALL)
またはINCLUDE ADD (ALL)
を使用します。どちらも結果は同じです。(すべてのパスを除外することはできません。)
この項では、XPath式のサブセットに対し、XMLIndex
索引を定義する方法を例示します。
例5-28 CREATE INDEXによるXMLIndexパスのサブセット化
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLINDEX PARAMETERS ('PATHS (INCLUDE (/PurchaseOrder/LineItems//* /PurchaseOrder/Reference))');
この文では、次に示すように、最上位要素であるPurchaseOrder
およびその子に対してのみ索引付けする索引を作成します。
すべてのLineItems
要素およびその子孫
すべてのReference
要素
索引に使用される一連の空白のパスに対し、指定のパスを含めていきます。
例5-29 ALTER INDEXによるXMLIndexパスのサブセット化
ALTER INDEX po_xmlindex_ix REBUILD PARAMETERS ('PATHS (INCLUDE ADD (/PurchaseOrder/Requestor /PurchaseOrder/Actions/Action//*))');
この文では、索引付けに使用されたパスに対し、2つのパスを追加します。これらのパスは、Requestor
要素と、Action
要素の子孫(およびその祖先)に対して索引付けします。
例5-30 名前空間接頭辞を使用したXMLIndexパスのサブセット化
XMLIndex
索引付けに使用されるXPath式で名前空間接頭辞が使用される場合、NAMESPACE MAPPING
句をPATHS
リストで使用して接頭辞を指定できます。次に例を示します。
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLIndex PARAMETERS ('PATHS INCLUDE (/PurchaseOrder/LineItems//* /PurchaseOrder/ipo:Reference) NAMESPACE MAPPING (xmlns="http://xmlns.oracle.com" xmlns:ipo="http://xmlns.oracle.com/ipo"))');
XMLIndex
パスのサブセット化には、次のルールが適用されます。
パスはchild軸およびdescendant軸のみを参照し、さらに、要素ノードおよび属性ノード、またはその名前(ワイルドカードを使用可能)のみをテストする必要があります。特に、パスには述語を含めないでください。
パス除外とパス包含を一度に指定できません。いずれかの方法を指定する必要があります。
パス除外(包含)によって索引が作成された場合は、パス除外(包含)によってのみ修正が可能です。索引の修正は、パスのサブセット化をさらに制限するか、さらに拡張するかのいずれかです。たとえば、特定のパスを含める索引を作成した後に、特定のパスを除外するよう修正することはできません。
データベース管理者(DBA)はOracle XML DBリポジトリのリソースに対してXMLIndex
索引を作成し、XMLデータまたはメタデータ(システム定義またはユーザー定義)に対する問合せを向上できます。
Oracle XML DBリポジトリに対してXMLIndex
索引を作成できるのは、データベース・ロールがXDBADMIN
のユーザーのみです。この索引を作成した後、実際に問合せされるリソースに制限します。
ビューの行、または階層対応していない表の行に対するREF
が(コンテンツまたはメタデータに)含まれているリソースに対しては、索引付けできません。これを試行すると、エラーが発生します。
データベース管理者としてこの手順を実行し、特定のリポジトリ・リソースに対してXMLIndex
索引を作成します。
リポジトリにXMLIndex
索引を作成します。作成される索引からは、リポジトリ・パス/Resource/ACL
、/Resource/RefCount
、および/Resource/RCList
は除外されます。パス表とすべての2次索引が作成されますが、リソースには索引付けしません。
CALL DBMS_XDB_ADMIN.CreateRepositoryXMLIndex();
この時点では、どのリソースにも索引付けされていません。手順2以降で索引付けされます。
索引に対し、リポジトリ・パスによってリポジトリ・リソースを指定します。これを行うには、DBMS_XDB_ADMIN
パッケージのPL/SQLプロシージャXMLIndexAddPath
を使用します。
DBMS_XDB_ADMIN.XMLIndexAddPath(<path to index>, <disable secondary indexes?>);
XMLIndexAddPath
への最初のパラメータは、索引に対するリソース(ファイルまたはフォルダ)をターゲットとするリポジトリ・パス式です。(注意: リポジトリ・パス式はXPath式ではありません。)次のパラメータはブール値です。値がTRUE
の場合は、XMLIndexAddPath
の実行中にパス表の2次索引のロードが無効になります。この値は、パス表の既存行が少なく、新規行が多数追加される場合にのみTRUE
に設定します。パスが索引付けされている間に2次索引を無効にすると、パス表の索引が更新されなくなります。具体的には、行が追加されるたびに、2次索引がロード(移入)されなくなります。これにより、リソースのバルク・ロードを高速化できます。
リポジトリに対して作成されたXMLIndex
索引を削除するには、次の手順を実行します。
CALL DBMS_XDB_ADMIN.DropRepositoryXMLIndex();
関連項目:
|
索引付けからリソースを削除するには、データベース管理者として次の手順を実行します。
リソースの各祖先に対してこの手順を実行し、まず索引付けから削除します。すべての祖先を索引付けから先に削除しなければ、リソースを索引付けから削除することはできません。
索引付けから削除するリポジトリ・リソースを、リポジトリ・パスで指定します。これを行うには、DBMS_XDB_ADMIN
パッケージのPL/SQLプロシージャXMLIndexRemovePath
を使用します。
DBMS_XDB_ADMIN.XMLIndexRemovePath(<path to index>, <recursively?>);
XMLIndexRemovePath
への最初のパラメータは、索引付けから削除するリソースをターゲットとするリポジトリ・パス式です。次のパラメータはブール値です。値がTRUE
の場合は、ターゲット化されたリソースと、そのすべての子孫が索引付けから削除されます。FALSE
の場合は、ターゲット化されたリソースのみが索引付けから削除されます。
関連項目: PL/SQLプロシージャであるDBMS_XDB_ADMIN.XMLIndexREmovePath の詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
リポジトリに問い合せるときにリポジトリ・データまたはメタデータのXMLIndex
を使用するには、ターゲット化されたすべてのリソースに対して索引付けする必要があります。問合せ時に、リポジトリ・パスによってリソースをターゲットにするには、SQL関数under_path
およびequals_path
を使用します。いずれの関数も使用しない場合は、under_path('/')
が使用されます。
例5-31は、リソース・データPurchaseOrder
要素に対する問合せを示します。Reference
要素の値はTFOX-20021009123335520PDT
です。
例5-31 リソース・データへの問合せにおけるXMLIndexの使用
SELECT ANY_PATH FROM RESOURCE_VIEW WHERE XMLExists('declare namespace r = "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :) /r:Resource/r:Contents/PurchaseOrder[Reference="TFOX-20021009123335520PDT"]' PASSING RES) AND under_path (RES, '/home/OE/PurchaseOrders/2002/') = 1; ANY_PATH -------------------------------------------------------------- /home/OE/PurchaseOrders/2002/Jan/TFOX-20021009123335520PDT.xml 1 row selected.
ここで示すunder_path
式は、XMLIndex
を使用して索引付けされたデータのみを含むパスに問合せを限定します。existsNode
式は、XPath式を使用するXMLノードをターゲットにしています。
リポジトリ・メタデータへも同様に問合せできます。そのためには、システム定義またはユーザー定義されたメタデータを表すリソース要素をターゲットにするのみです。例5-32は、システム・メタデータのCreationDate
要素の問合せを示します。
例5-32 リソース・メタデータへの問合せにおけるXMLIndexの使用
SELECT ANY_PATH FROM RESOURCE_VIEW
WHERE XMLExists('declare namespace r = "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
/r:Resource/r:CreationDate/text()=xs:dateTime("2005-02-07T18:31:53.093179")'
PASSING RES)
AND under_path (RES, '/home/OE/PurchaseOrders/2002/') = 1;
ANY_PATH
-----------------------------------------------------------------
/home/OE/PurchaseOrders/2002/Apr
/home/OE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336171PDT.xml
/home/OE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336271PDT.xml
/home/OE/PurchaseOrders/2002/Apr/EABEL-20021009123336251PDT.xml
/home/OE/PurchaseOrders/2002/Apr/PTUCKER-20021009123336191PDT.xml
/home/OE/PurchaseOrders/2002/Apr/PTUCKER-20021009123336291PDT.xml
. . .
144 rows selected.
Oracle XML DBリポジトリに対して作成されたXMLIndex
索引を削除できるのは、データベース・ロールがXDBADMIN
のユーザーのみです。リポジトリに対して作成されたXMLIndex
索引を削除するには、次の手順を実行します。
CALL DBMS_XDB_ADMIN.DropRepositoryXMLIndex();
関連項目: PL/SQLプロシージャであるDBMS_XDB_ADMIN.DropRepositoryXMLIndex の詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
XMLIndex
索引の作成または修正時にPARALLEL
句(程度は任意)を使用し、索引の作成とメンテナンスを並列的に行えます。これにより、索引の作成とメンテナンスのパフォーマンスを向上させることができます。また、問合せサーバーの各処理に対して個別に記憶域パラメータが適用されるため、記憶域の消費も多くなります。たとえば、INITIAL
値が5M、並列度が12で作成された索引は、作成時に少なくとも60Mの記憶域を消費します。
CREATE INDEX
およびALTER INDEX
のPARALLEL句の構文は、他のドメイン索引のものと同じです。
{ NOPARALLEL | PARALLEL [ integer ] }
例5-33では、並列度10でXMLIndex
索引を作成します。
例5-33 XMLIndex索引の並列的な作成
CREATE INDEX po_xmlindex_ix ON sale_info (sale_po_clob) INDEXTYPE IS XDB.XMLIndex
PARALLEL 10;
例5-33では、パス表と2次索引は、XMLIndex
索引そのものと同じ並列度(10)を継承して作成されます。パス表と2次索引に対して個別のPARALLEL
句を使用し、異なる並列度を設定することも可能です。例5-34を参照してください。
例5-34 XMLIndexの内部オブジェクトに対する、異なるPARALLEL度の使用
CREATE INDEX po_xmlindex_ix ON sale_info (sale_po_clob) INDEXTYPE IS XDB.XMLIndex PARAMETERS ('PATH TABLE po_path_table (PARALLEL 10) PATH ID INDEX po_pathid_ix ORDER KEY INDEX po_orderkey_ix (PARALLEL 5)') NOPARALLEL;
例5-34ではNOPARALLEL
が指定されているため、XMLIndex
索引そのものが連続して作成されます。パス表のPATHID
列の2次索引も連続で移入されます。これは、2次索引に対して明示的に並列度が指定されておらず、XMLIndex
索引から継承されるためです。パス表そのものは並列度を10として作成され、パス表のORDER_KEY
列の2次索引は、明示的な並列度指定を反映し、並列度5として移入されます。
XMLIndex
索引、パス表、またはその2次索引に対して指定した並列度は、後続のDML操作および問合せにおいて使用されます。
関連項目:
|
デフォルトでは、XMLIndex
索引付けはDML操作のたびに更新(メンテナンス)され、実表と常に同期化されます。場合によってはこれが不要になることもあり、従来の索引の使用も許容されることもあります。そのような場合は索引メンテナンスのコストを遅延させ、コミット時にのみ、またはデータベースの負荷が軽減されたときにのみ実行することもできます。これによりDMLパフォーマンスを向上させることができます。また、索引が同期されているときに未同期索引行のバルク・ロードを有効化することにより、索引メンテナンスのパフォーマンスを向上させることができます。
DML操作では従来の索引を使用しても、パフォーマンス以外には影響がありません。ただし、問合せ結果に影響を与えることもあります。問合せ時に索引が最新の状態でない場合は、問合せ結果も最新でない可能性があります。実表の1列のみがXMLType
データ型であったとしても、その表のすべての問合せには、XMLType
列のXMLIndex
索引の最終同期時のデータベース・データが反映されます。
CREATE INDEX
文またはALTER INDEX
文のPARAMETERS句を使用し、索引メンテナンスの遅延を指定できます。
XMLIndex
索引の同期化を遅延しても、次のデータベース操作により、索引が自動的に同期化されるので注意が必要です。
索引に対するDDL操作: ALTER INDEX
または2次索引の作成
実表に対するDDL操作: ALTER TABLE
または他の索引の作成
表5-4に、同期化オプションと、オプションの指定に使用されるASYNC
句の構文をまとめます。ASYNC
句は、CREATE INDEX
のPARAMETERS
句またはXMLIndex
のALTER INDEX
文で使用されます。
表5-4 索引の同期化
同期化するタイミング | ASYNC句の構文 |
---|---|
常時 |
これがデフォルトの動作です。前の |
コミット時 |
|
定期的 |
|
手動、オン・デマンド |
PL/SQLプロシージャ |
ASYNC
構文のオプションのパラメータであるSTALE
は、将来に備えて用意されているものであり、明示的に指定する必要はありません。ASYNC
がALWAYS
であれば、値はFALSE
になります。それ以外の場合の値はTRUE
です。このルールに反して明示的なSTALE
値を指定すると、エラーが発生します。
例5-35では、明日から毎週月曜日の午後3時に同期化されるXMLIndex索引を作成します。
例5-35 XMLIndexに対する遅延同期の指定
CREATE INDEX po_xmlindex_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS XDB.XMLIndex
PARAMETERS ('ASYNC (SYNC EVERY "FREQ=HOURLY; INTERVAL = 1")');
例5-36では、例5-35で作成された索引を手動で同期化します。
XMLIndex
索引の同期化が遅延されると、索引に対する最終同期化以降、実表に対して加えられたすべてのDML変更(挿入、更新、削除)は、DML操作当たり1行ずつ、表に記録されます。この表の名前は、静的なパブリック・ビューUSER_XML_INDEXES
、ALL_XML_INDEXES
、およびDBA_XML_INDEXES
のPEND_TABLE_NAME
列の値です。
この表を検証すると、指定のXMLIndex
索引を同期化させる最適な時期を決定できます。行数が多くなると、同期化が必要な索引も多くなります。
関連項目:
|
Oracle Databaseのコストベース・オプティマイザにより、使用される索引(ある場合)も含め、所定の問合せをどのように評価すると最も費用効率が高いかが決定します。これを正確に実行するには、様々なデータベース・オブジェクトの統計を収集する必要があります。
XMLIndex
については、通常はXMLIndex
索引が定義されている実表に関する統計のみ収集する必要があります(DBMS_STATS.gather_table_stats
プロシージャなどを使用)。これにより、XMLIndex
索引自体とパス表、および2次索引に関する統計が自動的に収集されます。実表の統計を削除すると(DBMS_STATS.delete_table_stats
プロシージャを使用)、他のオブジェクトに関する統計も削除されます。同様に、XMLIndex
索引に関する統計を収集すると(DBMS_STATS.gather_index_stats
プロシージャを使用)、パス表と2次索引に関する統計も収集されます。
例5-37では、実表po_clob
に関する統計を収集します。XMLIndex
索引、パス表、および2次パス表索引に関する統計が自動的に収集されます。
XMLIndex
を使用する際のガイドラインをいくつか示します。これらのガイドラインは、ここで説明する2つの方法によって同じ結果セットが戻される場合にのみ該当します。
祖先要素の接頭辞として//
を付加しないでください。例: /a/b
//c
ではなく、//c
を使用(これらが同じ結果セットを戻す場合)。
祖先要素の接頭辞として/*
を付加しないでください。例: /a
/*/*
ではなく、/*/*/*
を使用(これらが同じ結果セットを返す場合)。
いずれの場合にせよ、XMLType
の完全な表または列が必要であることがXPath式に示されている場合は、パフォーマンスが向上されないことからXMLIndex
は使用されないことに注意してください。たとえば、次の問合せで示すように、ドキュメント・ルート(/
)にアクセスする場合に該当します。
単独の結果を予期する場合は、extract
ではなくextractValue
とメソッドgetStringVal()
を使用します。そうすると、パス表のVALUE
列の索引を使用できます。(この場合は、XMLIndex
索引を作成する際、PARAMETERS
句でキーワードVALUE
を提供する必要があります。)
可能であれば、SELECT
句ではcount(extractValue(…))
ではなくcount(*)
を使用します。たとえば、発注書のLineItem
要素にDescription
の子が1つしかないことがわかっている場合は、次のように記述します。
SELECT count(*) FROM po_clob, XMLTable('//LineItem' PASSING OBJECT_VALUE);
次のように記述しないでください。
SELECT count(li.value) FROM po_clob p, XMLTable('//LineItem' PASSING p.OBJECT_VALUE COLUMNS value VARCHAR2(30) PATH '/LineItem/Description') li;
問合せのFROM
リストで使用されるXPath式の数は、なるべく少なくしてください。たとえば、次のように記述します。
SELECT li.description FROM po_clob p, XMLTable('PurchaseOrder/LineItems/LineItem' PASSING p.OBJECT_VALUE COLUMNS description VARCHAR2(256) PATH '/LineItem/Description') li;
次のように記述しないでください。
SELECT li.description FROM po_clob p, XMLTable('PurchaseOrder/LineItems' PASSING p.OBJECT_VALUE) ls, XMLTable('LineItems/LineItem' PASSING ls.OBJECT_VALUE COLUMNS description VARCHAR2(256) PATH '/LineItem/Description') li;
仮想表(XMLTable
SQL関数などで作成)の内部をドリルダウンするために、問合せでXPath式を使用する場合は、sys_orderkey_depth
SQL関数を使用してパス表の順序キーの2次索引を作成します。このような問合せを次に例示します。仮想的な明細項目表li
内のDescription
要素にナビゲートします。
SELECT li.description FROM po_clob p, XMLTable('PurchaseOrder/LineItems/LineItem' PASSING p.OBJECT_VALUE COLUMNS description VARCHAR2(256) PATH '/LineItem/Description') li;
このような問合せはsys_orderkey_depth
関数によって評価されます。この関数は、order-key値の深度を戻します。順序索引は2列を使用するため、必要となる索引は、ORDER_KEY
列およびRID
列、およびORDER_KEY
値に対して適用されたsys_orderkey_depth
関数のコンポジット索引です。次に例を示します。
CREATE INDEX depth_ix ON my_path_table (RID, sys_orderkey_depth(ORDER_KEY), ORDER_KEY);
この項では、XMLIndex
で使用する場合の、SQL関数CREATE INDEX
およびALTER INDEX
のPARAMETERS
句の構文を示します。
PARAMETERS
句はPARAMETERS ('
XMLIndex_parameters
')
であり、XMLIndex_parameters
とはXMLIndex_parameter_clause
の1回以上の繰返しを指します。
XMLIndex_parameters ::=
XMLIndex_parameter_clause ::=
create_index_paths_clause ::=
alter_index_paths_clause ::=
namespace_mapping_clause ::=
path_table_clause ::=
path_id_clause ::=
order_key_clause ::=
xml_index_value_clause ::=
どのXMLIndex_parameters
句でも、XMLIndex_parameter_clause
を1種類当たり最大で1回使用できます。たとえば、PATHS
句を最大で1回、path_table_clause
を最大で1回などです。
XMLIndex_parameter_clause
句は、表レベルでのみ、かつ、パスの追加と削除にのみ、ALTER INDEX
で使用できます。
PATHS
句を使用する際には、次の点を考慮する必要があります。
CREATE INDEX
文では、PATHS
句を最大で1回使用できます。つまり、create_index_paths_clause
の後に、PATHS
を最大で1回使用できます。
create_index_paths_clause
句はCREATE INDEX
でのみ、また、alter_index_paths_clause
句はALTER INDEX
でのみ使用されます。
create_index_paths_clause
およびalter_index_paths_clause
を使用する際には、次の点を考慮する必要があります。
INDEX_ALL_PATHS
句は、すべてのパスが含まれた状態で索引を再構築します。
索引に対するパスの明示的なリストには、ワイルドカードおよび//
を使用できます。
XPaths_list
は1つ以上のXpaths式で構成されるリストです。それぞれのリストには、child軸、descendant軸、名前テスト、およびワイルドカード(*
)構造のみが含まれます。
XPaths_list
が省略されていると、すべての文書にあるすべての情報が索引付けされます。
XPaths_list
のXPath式で使用される一意の名前空間接頭辞に対し、対応する名前空間情報を提供するには、標準的なXML名前空間宣言が必要です。
索引を削除した後で必要に応じて作成しなおすと、構文に直接反映されない方法で索引を変更できます。たとえば、パスを含めることで定義される索引を、パスを除外することで定義される索引に変更する場合は、索引を削除した後で、EXCLUDE
を使用して作成しなおします。
xml_index_value_clause
を使用する際には、次の点を考慮する必要があります。
VALUE
列は、VARCHAR2(4000)
として作成されています。
xml_index_value_clause
句がキーワードVALUE
でのみ構成される場合は、通常のデフォルト属性によって値索引が作成されます。
path_id_clause
句がキーワードPATH ID
でのみ構成される場合は、通常のデフォルト属性によってパスID索引が作成されます。
order_key_clause
句がキーワードORDER KEY
でのみ構成される場合は、通常のデフォルト属性によって順序キー索引が作成されます。
ASYNC
句を使用する際には、次の点を考慮する必要があります。
ALWAYS
とは、各DML文に対して自動同期が行われることを意味します。
MANUAL
とは、自動同期が行われないことを意味します。DBMS_XMLINDEX.SyncIndex
を使用して、索引を手動同期させる必要があります。
EVERY
repeat_interval
とは、repeat_interval
の間隔で索引を自動同期させることを意味します。repeat_interval
の構文は、PL/SQLパッケージDBMS_SCHEDULER
と同じであり、二重引用符("
)で囲む必要があります。EVERY
を使用するには、CREATE JOB
権限が必要です。
ON COMMIT
とは、コミット操作の直後に索引を同期させることを意味します。コミットは、同期が完了するまでは戻されません。同期は個別の処理として実行されるため、データがコミットされてから、索引の変更がコミットされるまで短い間隔が生じることがあります。
STALE
はオプションです。値がTRUE
の場合は、問合せ結果が失効している可能性があります。値がFALSE
の場合は、問合せ結果は常に最新です。デフォルト値と、明示的に指定可能な唯一の値は次のとおりです。
ALWAYS
の場合、STALE
はTRUE
です。
ALWAYS
以外のASYNC
オプションの場合、STALE
はFALSE
です。
関連項目:
|
XMLType
列にOracle Text索引を作成できます。Oracle TextのCONTEXT
索引では、XMLの全文検索を実行するためのSQL関数contains
を使用できます。構造化記憶域では、XPathリライトによりora:contains
XPath関数がcontains
SQL関数にリライトされることが多いため、このようなケースでもOracle Text索引が使用されます。
Oracle Text索引を作成するには、CREATE INDEX
を使用します。そのとき、例5-38で示すように、INDEXTYPE
をCTXSYS.CONTEXT
に指定します。
例5-38 Oracle Text索引の作成
CREATE INDEX po_otext_ix ON po_clob (OBJECT_VALUE) INDEXTYPE IS CTXSYS.CONTEXT; Index created.
XMLType
列に対して、contains
やscore
などのOracle Text操作を実行することもできます。例5-39に、contains
SQL関数を使用したOracle Text検索を示します。
例5-39 SQL関数CONTAINSを使用したXMLデータの検索
SELECT DISTINCT extractValue(OBJECT_VALUE,
'/PurchaseOrder/ShippingInstructions/address') "Address"
FROM po_clob
WHERE contains(OBJECT_VALUE,
'$(Fortieth) INPATH (PurchaseOrder/ShippingInstructions/address)') > 0;
Address
------------------------------
1200 East Forty Seventh Avenue
New York
NY
10024
USA
1 row selected.
この問合せの実行計画は、Oracle TextのCONTEXT
索引が使用されていることを2通りの方法で示します。索引をドメイン索引として明示的に参照している点と、contains
SQL関数を述語情報で参照している点です。
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------- Plan hash value: 274475732 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 7 | 14098 | 10 (10)| 00:00:01 | | 1 | HASH UNIQUE | | 7 | 14098 | 10 (10)| 00:00:01 | | 2 | TABLE ACCESS BY INDEX ROWID| PO_CLOB | 7 | 14098 | 9 (0)| 00:00:01 | |* 3 | DOMAIN INDEX | PO_OTEXT_IX | | | 4 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("CTXSYS"."CONTAINS"(SYS_MAKEXML('2B0A2483AB140B35E040578C8A173FEC',523 3,"XMLDATA"),'$(Fortieth) INPATH (PurchaseOrder/ShippingInstructions/address)')>0) 20 rows selected.
Oracle Textの索引付けは、この章で説明するその他の索引付けに完全に直交しています。contains
SQL関数またはora:contains
XPath関数が使用されると、Oracle Text索引を全文検索で使用できます。
例5-40に、同じXMLデータに対してXMLIndex
索引とOracle Text索引の両方が定義されているケースを示します。問合せは、例5-39と同じです。Oracle Text索引が、例5-14のXMLIndex
パス表のVALUE
列に作成されます。
例5-40 Oracle Text索引およびXMLIndex索引の使用
CREATE INDEX po_otext_ix ON my_path_table (VALUE) INDEXTYPE IS CTXSYS.CONTEXT; Index created. EXPLAIN PLAN FOR SELECT DISTINCT extractValue(OBJECT_VALUE, '/PurchaseOrder/ShippingInstructions/address') "Address" FROM po_clob WHERE contains(OBJECT_VALUE, '$(Fortieth) INPATH (PurchaseOrder/ShippingInstructions/address)') > 0; Explained. -- SET ECHO OFF; PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------- Plan hash value: 2664483039 ------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2014 | 3 (34)| 00:00:01 | |* 1 | TABLE ACCESS BY INDEX ROWID| MY_PATH_TABLE | 1 | 3524 | 1 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | SYS78942_PO_XMLINDE_ORDKEY_IX | 1 | | 2 (0)| 00:00:01 | | 3 | HASH UNIQUE | | 1 | 2014 | 3 (34)| 00:00:01 | |* 4 | TABLE ACCESS FULL | PO_CLOB | 1 | 2014 | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("SYS_P0"."PATHID"=HEXTORAW('35EF580A') AND SYS_XMLI_LOC_ISNODE("SYS_P0"."LOCATOR")=1) 2 - access("SYS_P0"."RID"=:B1) filter("SYS_P0"."RID"=:B1) 4 - filter("CTXSYS"."CONTAINS"(SYS_MAKEXML("PO_CLOB"."XMLDATA"),'$(Fortieth) INPATH (PurchaseOrder/ShippingInstructions/address)')>0) Note ----- - dynamic sampling used for this statement 24 rows selected.
例5-40の実行計画では、XMLIndex
索引とOracle Text索引の両方を参照しており、両方が使用されていることを示します。
XMLIndex
索引は、パス表MY_PATH_TABLE
と、その順序キー索引SYS78942_PO_XMLINDE_ORDKEY_IX
によって示されます。
Oracle Text索引は、述語情報のcontains
SQL関数への参照によって示されます。
脚注の凡例
脚注1: 実際のパス表の実装は多少異なることがあります。