次の方法で共有


XML インデックス (SQL Server)

XML インデックスは、 xml データ型の列に作成できます。 列内の XML インスタンスに対するすべてのタグ、値、パスにインデックスを付け、クエリのパフォーマンスを向上させます。 アプリケーションは、次のような状況で XML インデックスの恩恵を受ける可能性があります。

  • ワークロードで XML 列へのクエリが頻繁に行われる場合。 データの変更中の XML インデックスのメンテナンス コストを考慮する必要があります。

  • XML 値は比較的大きく、取得される部分は比較的小さくなります。 インデックスを作成すると、実行時にデータ全体が解析されるのを回避し、効率的なクエリ処理のためにインデックス検索にメリットがあります。

XML インデックスは、次のカテゴリに分類されます。

  • プライマリ XML インデックス

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

xml型列の最初のインデックスは、プライマリ XML インデックスである必要があります。 プライマリ XML インデックスを使用すると、次の種類のセカンダリ インデックス (PATH、VALUE、PROPERTY) がサポートされます。 これらのセカンダリ インデックスは、クエリの種類によっては、クエリのパフォーマンス向上に役立つ場合があります。

xmlデータ型を操作するためにデータベース オプションが正しく設定されていない限り、XML インデックスを作成または変更することはできません。 詳細については、「 XML 列で Full-Text 検索を使用する」を参照してください。

XML インスタンスは、大きなバイナリ オブジェクト (BLOB) として xml 型の列に格納されます。 これらの XML インスタンスは大きくなる可能性があり、 xml データ型インスタンスの格納されたバイナリ表現は最大 2 GB にすることができます。 インデックスがない場合、これらのバイナリ ラージ オブジェクトは実行時に細分化され、クエリが評価されます。 この細断は時間がかかる場合があります。 たとえば、次のクエリについて考えてみます。

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  

WHERE句の条件を満たす XML インスタンスを選択するために、テーブル Production.ProductModelの各行の XML バイナリ ラージ オブジェクト (BLOB) が実行時に細分化されます。 次に、exist()メソッドの式(/PD:ProductDescription/@ProductModelID[.="19"]) が評価されます。 この実行時の細断は、列に格納されているインスタンスのサイズと数に応じて、コストがかかる場合があります。

アプリケーション環境で XML バイナリ ラージ オブジェクト (BLOB) のクエリを実行するのが一般的な場合は、 xml 型の列にインデックスを付けるのに役立ちます。 ただし、データの変更中にインデックスを維持することに関連するコストが発生します。

プライマリ XML インデックス

プライマリ XML インデックスは、XML 列内の XML インスタンス内のすべてのタグ、値、パスにインデックスを付けます。 プライマリ XML インデックスを作成するには、XML 列が存在するテーブルに、テーブルの主キーに対するクラスター化インデックスが必要です。 SQL Server では、この主キーを使用して、プライマリ XML インデックス内の行と、XML 列を含むテーブル内の行を関連付けます。

プライマリ XML インデックスは、 xml データ型列の XML BLOB の細分化および永続化された表現です。 列の XML バイナリ ラージ オブジェクト (BLOB) ごとに、インデックスによって複数のデータ行が作成されます。 インデックス内の行数は、XML バイナリ ラージ オブジェクト内のノードの数とほぼ同じです。 クエリが完全な XML インスタンスを取得すると、SQL Server は XML 列からインスタンスを提供します。 XML インスタンス内のクエリはプライマリ XML インデックスを使用し、インデックス自体を使用してスカラー値または XML サブツリーを返すことができます。

各行には、次のノード情報が格納されます。

  • 要素や属性名などのタグ名。

  • ノード値。

  • 要素ノード、属性ノード、テキスト ノードなどのノードの種類。

  • 内部ノード識別子で表されるドキュメント注文情報。

  • 各ノードから XML ツリーのルートへのパス。 この列は、クエリ内のパス式を検索します。

  • ベース テーブルの主キー。 ベース テーブルの主キーは、ベース テーブルとの逆結合のプライマリ XML インデックスに複製され、ベース テーブルの主キーの列の最大数は 15 に制限されます。

このノード情報は、指定されたクエリの XML 結果を評価および構築するために使用されます。 最適化のために、タグ名とノードの種類の情報は整数値としてエンコードされ、Path 列は同じエンコードを使用します。 また、パス サフィックスのみがわかっている場合は、パスの照合を許可するために、パスが逆順に格納されます。 例えば次が挙げられます。

  • //ContactRecord/PhoneNumber 最後の 2 つの手順のみがわかっている場合

または

  • /Book/*/Title ここで、ワイルドカード文字 (*) は式の途中で指定されます。

クエリ プロセッサは、 xml データ型メソッド を含むクエリにプライマリ XML インデックスを使用し、プライマリ インデックス自体からスカラー値または XML サブツリーを返します。 (このインデックスには、XML インスタンスを再構築するために必要なすべての情報が格納されます)。

たとえば、次のクエリは、ProductModel テーブルのCatalogDescription``xml型の列に格納されている概要情報を返します。 このクエリは、カタログの説明にも<Features>の説明が格納されている製品モデルの<Summary>情報のみを返します。

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS "PD")SELECT CatalogDescription.query('  /PD:ProductDescription/PD:Summary') as ResultFROM Production.ProductModelWHERE CatalogDescription.exist ('/PD:ProductDescription/PD:Features') = 1  

プライマリ XML インデックスに関しては、ベース テーブル内の各 XML バイナリ ラージ オブジェクト インスタンスを細断するのではなく、各 XML バイナリ ラージ オブジェクトに対応するインデックス内の行が、 exist() メソッドで指定された式を順番に検索します。 パスがインデックスの Path 列にある場合、 <Summary> 要素とそのサブツリーはプライマリ XML インデックスから取得され、 query() メソッドの結果として XML バイナリ ラージ オブジェクトに変換されます。

完全な XML インスタンスを取得するときに、プライマリ XML インデックスは使用されないことに注意してください。 たとえば、次のクエリは、特定の製品モデルの製造手順を記述する XML インスタンス全体をテーブルから取得します。

USE AdventureWorks2012;SELECT InstructionsFROM Production.ProductModel WHERE ProductModelID=7;  

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

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

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

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

  • プロパティ セカンダリ XML インデックス

1 つ以上のセカンダリ インデックスを作成するためのガイドラインを次に示します。

  • ワークロードで XML 列でパス式が大幅に使用されている場合、PATH セカンダリ XML インデックスによってワークロードが高速化される可能性があります。 最も一般的なケースは、Transact-SQL の WHERE 句の XML 列で exist() メソッドを使用することです。

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

  • ワークロードで、それらの値を含む要素名または属性名がわからない状態で XML インスタンス内の値のクエリを実行する必要がある場合は、VALUE インデックスを作成できます。 これは通常、//author[last-name="Howard"] などの子孫軸参照で発生します。ここで、 <author> 要素は階層の任意のレベルで実行できます。 また、/book [@* = "novel"] などのワイルドカード クエリでも発生します。このクエリでは、値 "novel" を持つ属性を持つ <book> 要素が検索されます。

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 インデックス内の直接シークが可能になり、プライマリ インデックス内のパス値の順次検索よりも検索パフォーマンスが向上します。

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句は、AdditionalContactInfo``xml型列の値を検索するフィルターを指定します。 連絡先 ID は、対応する追加の連絡先情報 XML バイナリ ラージ オブジェクトに特定の電話番号が含まれている場合にのみ返されます。 < telephoneNumber >要素は XML 内の任意の場所に表示される可能性があるため、パス式は降順または自己軸を指定します。

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> の検索値はわかっていますが、XML インスタンス内の任意の場所に、 <telephoneNumber> 要素の子として表示できます。 この種類のクエリは、特定の値に基づくインデックス検索のメリットを得られる場合があります。

プロパティ セカンダリ インデックス

個々の XML インスタンスから 1 つ以上の値を取得するクエリは、PROPERTY インデックスの恩恵を受ける可能性があります。 このシナリオは、xml型の value() メソッドを使用してオブジェクトのプロパティを取得し、オブジェクトの主キー値がわかっている場合に発生します。

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

たとえば、製品モデルの19の場合、次のクエリでは、value() メソッドを使用してProductModelIDProductModelName属性値を取得します。 プライマリ 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 ステートメントを使用できます。

XML インデックスに関する情報の取得

XML インデックス エントリは、カタログ ビューの sys.indexes に、インデックス "type" 3 と共に表示されます。 name 列には、XML インデックスの名前が含まれています。

XML インデックスは、カタログ ビューの sys.xml_indexes にも記録されます。 これには、sys.indexes のすべての列と、XML インデックスに役立ついくつかの特定の列が含まれます。 列の値 NULL (secondary_type) は、プライマリ XML インデックスを示します。値 'P'、'R' および 'V' は、それぞれ PATH、PROPERTY、VALUE のセカンダリ XML インデックスを表します。

XML インデックスの領域の使用は、テーブル値関数 sys.dm_db_index_physical_statsにあります。 これは、すべてのインデックスの種類について、占有されているディスク ページの数、平均行サイズ (バイト単位)、レコード数などの情報を提供します。 これには、XML インデックスも含まれます。 この情報は、各データベース パーティションで使用できます。 XML インデックスでは、ベース テーブルと同じパーティション構成とパーティション分割関数が使用されます。

こちらもご覧ください

sys.dm_db_index_physical_stats (Transact-SQL)
XML データ (SQL Server)