セカンダリ XML インデックス

検索のパフォーマンスを向上するために、セカンダリ XML インデックスを作成できます。セカンダリ XML インデックスを作成する前に、プライマリ XML インデックスが存在している必要があります。セカンダリ XML インデックスの種類を次に示します。

  • PATH セカンダリ XML インデックス

  • VALUE セカンダリ XML インデックス

  • PROPERTY セカンダリ XML インデックス

次に、セカンダリ インデックスを 1 種類以上作成する場合のガイドラインを示します。

  • ワークロードで XML 列にパス式が多用されている場合、PATH セカンダリ XML インデックスを作成するとワークロードを高速に処理できることがあります。一般的な例では、Transact-SQL の WHERE 句で XML 列に対し exist() メソッドが使用される場合があります。

  • パス式を使用して個々の XML インスタンスから複数の値を取得する場合、PROPERTY インデックスで各 XML インスタンス内のパスをクラスタ化すると効果が得られる可能性があります。このシナリオは、主キーの値がわかっていてオブジェクトのプロパティをフェッチするプロパティ バッグ シナリオで主に発生します。

  • XML インスタンスの値を、要素名または属性名がわからないままクエリで取得する場合、VALUE インデックスを作成できます。//author[last-name="Howard"] (<author> 要素が階層のどのレベルにあってもよい) のように、descendant 軸を参照する場合がその典型です。また、ワイルドカードを使用するクエリ (いずれかの属性に値 "novel" が指定された <book> 要素をクエリで検索する /book [@* = "novel"] など) もこれに該当します。

PATH セカンダリ XML インデックス

クエリで xml 型列のパス式をよく指定している場合、PATH セカンダリ インデックスにより検索速度を向上できる場合があります。このトピックで既に説明したように、WHERE 句に exist() メソッドを指定するクエリを使用する場合には、プライマリ インデックスが役に立ちます。PATH セカンダリ インデックスを追加することでも、そのようなクエリの検索パフォーマンスが向上する場合があります。

プライマリ XML インデックスにより、XML バイナリ ラージ オブジェクトを実行時に細分化せずに済むようになりますが、パス式に基づくクエリのパフォーマンスが最適にならない場合があります。XML バイナリ ラージ オブジェクトに対応するプライマリ XML インデックスのすべての行は大きな XML インスタンスに対して順番に検索されるので、検索速度が低下する場合があります。このような場合、プライマリ インデックスのパス値とノード値にセカンダリ インデックスを構築すると、インデックス検索の速度を大幅に向上できます。PATH セカンダリ インデックスではパス値とノード値がキー列になり、パスの検索時により効率的にシークできるようになります。クエリ オプティマイザでは、次に示すような式に PATH インデックスを使用できます。

  • /root/Location : パスだけを指定しています。

または

  • /root/Location/@LocationID[.="10"] : パスとノード値の両方を指定しています。

次のクエリでは、PATH インデックスが役立つケースを示します。

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS "PD")

SELECT CatalogDescription.query('
  /PD:ProductDescription/PD:Summary
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist ('/PD:ProductDescription/@ProductModelID[.="19"]') = 1

このクエリでは、exist() メソッド内のパス式 /PD:ProductDescription/@ProductModelID と値 "19" が PATH インデックスのキー フィールドに対応しています。これにより、PATH インデックス内を直接シークできるようになり、プライマリ XML インデックスでパス値を順番に検索するよりも検索のパフォーマンスが向上します。

VALUE セカンダリ XML インデックス

/Root/ProductDescription/@*[. = "Mountain Bike"] や //ProductDescription[@Name = "Mountain Bike"] などのように、クエリが値に基づいており、パスが完全に指定されていない場合や、パスにワイルドカードが含まれている場合は、プライマリ XML インデックスのノード値にセカンダリ XML インデックスを構築すると、より迅速に結果を得られる場合があります。

VALUE インデックスのキー列は、プライマリ XML インデックスの列 (ノード値とパス) です。値を格納している要素名または属性名がわからない状態で XML インスタンスの値に対するクエリを実行する作業がワークロードに含まれている場合、VALUE インデックスが役立つことがあります。たとえば、次の式は VALUE インデックスを使用すると効率的になります。

  • //author[LastName="someName"] : <LastName> 要素の値はわかっていますが、親である <author> はどこにでも存在し得ます。

  • /book[@* = "someValue"] : "someValue" という値の属性を持つ <book> 要素を検索します。

次のクエリは、Contact テーブルから ContactID を返します。WHERE 句では、AdditionalContactInfoxml 型列の値を検索するフィルタを指定しています。連絡先 ID は、対応する追加の連絡先情報の XML バイナリ ラージ オブジェクトに特定の電話番号が含まれている場合にのみ返されます。<telephoneNumber> 要素は XML 内のどこにでも存在し得るので、パス式で descendent-or-self 軸を指定しています。

WITH XMLNAMESPACES (
  'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo' AS CI,
  'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes' AS ACT)

SELECT ContactID 
FROM   Person.Contact
WHERE  AdditionalContactInfo.exist('//ACT:telephoneNumber/ACT:number[.="111-111-1111"]') = 1

この場合、検索する <number> の値はわかっていますが、この値は <telephoneNumber> 要素の子として XML インスタンス内のどこにでも存在できます。このようなクエリでは特定の値に基づいてインデックス参照を行うと、効率的になる場合があります。

PROPERTY セカンダリ XML インデックス

個々の XML インスタンスから 1 つ以上の値を取得するクエリでは、PROPERTY インデックスを使用するとメリットが得られる場合があります。xml 型の value() メソッドを使用してオブジェクトのプロパティを取得する場合や、オブジェクトの主キー値が既知である場合にこのような状況が発生します。

PROPERTY インデックスは、プライマリ XML インデックスの列 (PK、パス、およびノード値) について構築されます。PK はベース テーブルの主キーです。

たとえば、次のクエリでは、製品モデル 19 の ProductModelID 属性と ProductModelName 属性の値を value() メソッドを使用して取得しています。プライマリ XML インデックスや他のセカンダリ XML インデックスではなく PROPERTY インデックスを使用すると、クエリをより迅速に実行できる場合があります。

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS "PD")

SELECT CatalogDescription.value('(/PD:ProductDescription/@ProductModelID)[1]', 'int') as ModelID,
       CatalogDescription.value('(/PD:ProductDescription/@ProductModelName)[1]', 'varchar(30)') as ModelName        
FROM Production.ProductModel   
WHERE ProductModelID = 19

このトピックの後半で説明する違いを除けば、xml 型列の XML インデックスは、xml 以外の型の列のインデックスと同様に作成できます。XML インデックスの作成と管理には、次の Transact-SQL DDL ステートメントを使用できます。