Index XML (SQL Server)

Des index XML peuvent être créés sur des colonnes de type xml. L'indexation porte sur les balises, les valeurs et les chemins d'accès rencontrés dans les instances XML de la colonne et contribue à l'optimisation des performances des requêtes. Votre application peut bénéficier d'un index XML dans les situations suivantes :

  • Les requêtes portant sur des colonnes XML sont fréquentes dans votre charge de travail. Le coût de la maintenance des index XML au cours de la modification des données doit être pris en compte lors de l'évaluation des avantages.

  • Vos valeurs XML sont relativement grandes et les parties récupérées relativement petites. En créant un index, vous n'avez plus à analyser l'ensemble des données lors de l'exécution et pouvez profiter de la recherche d'index pour accélérer le traitement des requêtes.

Les index XML sont classés en plusieurs catégories :

  • Index XML primaires

  • Index XML secondaires

Le premier index portant sur la colonne de type xml est obligatoirement l'index XML primaire. Par le biais de l’index XML primaire, les trois types d’index secondaires suivants sont pris en charge : PATH, VALUE et PROPERTY. Selon le type de requêtes, ces index secondaires peuvent contribuer à améliorer les performances liées à l'exécution de requêtes.

Notes

Vous ne pouvez pas créer ou modifier d'index XML à moins que les options de base de données ne soient définies correctement pour utiliser le type de données xml. Pour plus d’informations, consultez Utiliser la recherche en texte intégral avec des colonnes XML.

Les instances XML sont stockées dans les colonnes de type xml sous forme de BLOB (Binary Large Objects, objets volumineux binaires). Ces instances XML peuvent donc être volumineuses et la représentation binaire stockée d'instances de type xml peut atteindre jusqu'à 2 Go. Sans index, ces objets sont fragmentés au moment de l'exécution du programme afin d'évaluer une requête, ce qui peut prendre du temps. Examinons, par exemple, la requête suivante :

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  

Pour pouvoir sélectionner les instances XML satisfaisant la condition stipulée dans la clause WHERE , le BLOB XML se trouvant dans chaque ligne de la table Production.ProductModel est fragmenté au moment de l'exécution. L'expression (/PD:ProductDescription/@ProductModelID[.="19"]) tirée de la méthode exist() est ensuite évaluée. Une telle fragmentation à l'exécution peut être coûteuse selon la taille et le nombre d'instances stockées dans la colonne.

Si l'exécution de requêtes sur des BLOB est courante dans l'environnement de votre application, cette méthodologie permet d'indexer les colonnes de type xml. En contrepartie, le coût associé à la gestion de l'index lors de la modification des données est également à prendre en compte.

Index XML primaires

L'index XML primaire indexe toutes les balises, valeurs et chemins d'accès rencontrés dans les instances XML d'une colonne XML. Pour créer un index XML primaire, la table contenant la colonne XML doit posséder un index cluster portant sur la clé primaire de la table. SQL Server utilise cette clé primaire pour corréler les lignes de l'index XML primaire avec des lignes dans la table qui contient la colonne XML.

L'index XML primaire correspond à une représentation fragmentée et persistante des objets blob XML inclus dans la colonne des données de type xml. Pour chacun de ces objets blob XML de la colonne, l'index crée plusieurs lignes de données. Le nombre de lignes dans l'index est presque égal au nombre de nœuds se trouvant dans l'objet blob XML. Lorsqu'une requête extrait l'intégralité de l'instance XML, SQL Server fournit l'instance à partir de la colonne XML. Les requêtes dans des instances XML utilisent l'index XML primaire et peuvent renvoyer des valeurs scalaires ou des sous-arborescences XML en se servant de l'index lui-même.

Chaque ligne stocke les informations suivantes relatives aux nœuds :

  • Le nom de la balise tel que le nom d'un élément ou d'un attribut.

  • La valeur du nœud.

  • Le type de nœud, par exemple un nœud élément, un nœud attribut ou un nœud texte.

  • Les informations sur l'ordre du document, représentées par un identifiant de nœud interne.

  • Le chemin d'accès de chacun des nœuds vers la racine de l'arborescence XML. Cette colonne fait l'objet de recherches pour y trouver la présence d'expressions de chemin d'accès mentionnées dans la requête.

  • La clé primaire de la table de base. Cette clé est copiée dans l'index XML primaire afin de pouvoir effectuer une jointure en retour avec la table de base et le nombre maximal de colonnes dans la clé primaire de la table de base est limité à 15.

Les informations de ce nœud sont utilisées afin d'évaluer et d'élaborer les résultats sous forme de données XML découlant d'une requête donnée. Pour des raisons d'optimisation, les informations relatives au nom de la balise et au type de nœud sont encodées sous forme de valeurs entières et la colonne Path s'appuie sur ce même encodage. En outre, les chemins d'accès sont stockés dans l'ordre inverse afin de pouvoir faire correspondre les chemins d'accès où seul le suffixe est connu. Par exemple :

  • //ContactRecord/PhoneNumber , où seuls les deux derniers niveaux sont connus ;

OR

  • /Book/*/Title où le caractère générique (*) est mentionné au milieu de l’expression.

Le processeur de requêtes utilise l'index XML primaire dans le cas de requêtes mettant en œuvre des xml Data Type Methods et renvoie les valeurs scalaires ou les sous-arborescences XML tirées de l'index primaire lui-même (cet index stocke toutes les informations nécessaires afin de reconstruire l'instance XML).

Par exemple, la requête suivante retourne des informations récapitulatives stockées dans la CatalogDescription``xml colonne type de la ProductModel table. La requête retourne <Summary> des informations uniquement pour les modèles de produit dont la description du catalogue stocke également la <Features> description.

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  

Concernant l'index XML primaire, au lieu de fragmenter chaque instance d'objet blob XML se trouvant dans la table de base, les lignes de l'index correspondant à chaque objet blob XML sont soumises à des recherches séquentielles pour retrouver l'expression indiquée dans la méthode exist() . Si le chemin d’accès se trouve dans la colonne Path de l’index, l’élément <Summary> ainsi que ses sous-arborescences sont récupérés à partir de l’index XML principal et convertis en un grand objet binaire XML à la suite de la query() méthode .

Notez que l'index XML primaire n'est pas sollicité lors de la récupération d'une instance XML complète. Par exemple, la requête suivante extrait de la table l'instance XML tout entière décrivant les instructions de fabrication d'un modèle de produit donné.

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

Index XML secondaires

Afin d'améliorer les performances lors des recherches, vous pouvez créer des index XML secondaires. Un index XML primaire doit être défini au préalable avant de pouvoir créer des index secondaires. Il en existe trois types différents :

  • les index XML secondaires de type PATH (s'appuyant sur le chemin d'accès) ;

  • les index XML secondaires de type VALUE (utilisant la valeur comme critère de recherche) ;

  • les index XML secondaires de type PROPERTY (pour rechercher des données d'après leurs propriétés).

Voici quelques consignes pour vous aider à créer un ou plusieurs index secondaires :

  • Si votre charge de travail utilise souvent des expressions de chemin sur les colonnes XML, l'index secondaire PATH a toutes les chances de l'accélérer. C’est ce que vous pouvez constater le plus souvent en cas d’utilisation de la méthode exist() sur des colonnes XML dans la clause WHERE de Transact-SQL.

  • Si votre charge de travail récupère plusieurs valeurs d'instances XML individuelles en utilisant des expressions de chemin, le clustering des chemins pour chaque instance XML dans l'index PROPERTY peut s'avérer fort utile. Ce scénario se produit généralement avec un sac de propriétés où les propriétés d'un objet sont récupérées et la valeur de sa clé primaire est connue.

  • Si votre charge de travail implique le lancement de requêtes sur des valeurs d'instances XML pour lesquelles vous ne connaissez pas les noms d'élément ou d'attribut, vous aurez peut-être intérêt à créer l'index VALUE. Cela se produit généralement avec les recherches d’axes descendants, comme //author[last-name="Howard"], où <les éléments d’auteur> peuvent se produire à n’importe quel niveau de la hiérarchie. Il se produit également dans les requêtes génériques, telles que /book [@* = « novel"], où la requête recherche <des éléments de livre> qui ont un attribut ayant la valeur « novel ».

les index XML secondaires de type PATH (s'appuyant sur le chemin d'accès) ;

Si vos requêtes précisent habituellement les expressions de chemin d'accès sur les colonnes de type xml, un index secondaire de type PATH peut s'avérer à même d'accélérer la recherche. Comme nous l’avons vu précédemment, l’index primaire est des plus utiles pour les requêtes indiquant la méthode exist() dans leur clause WHERE. Si vous ajoutez à présent un index secondaire de type PATH, il se peut que vous amélioriez encore la rapidité de la recherche lancée par de telles requêtes.

Bien qu'un index XML primaire évite de fragmenter les objets blob XML à l'exécution, il peut ne pas offrir les meilleurs temps de réponse pour les requêtes s'appuyant sur des expressions de chemin d'accès. Une recherche, lancée sur toutes les lignes constituant l'index XML primaire correspondant à un objet blob XML et s'opérant de façon séquentielle pour des instances XML volumineuses, peut s'avérer des plus lentes. Dans ce cas, un index secondaire construit sur les valeurs de chemin d'accès et sur celles des nœuds de l'index primaire peut accélérer de façon significative la recherche sur l'index. Dans le cas d'un index XML secondaire de type PATH, les valeurs de chemin d'accès et des nœuds correspondent à des colonnes clés permettant donc des recherches plus efficaces si ces dernières portent sur le chemin d'accès. Il se peut que l'optimiseur de requête utilise l'index de type PATH dans des expressions telles que celles mentionnées ci-dessous :

  • /root/Location , n'indiquant que son chemin d'accès ;

OR

  • /root/Location/@LocationID[.="10"] , où le chemin et la valeur du nœud sont précisés.

La requête suivante illustre un cas de figure où l'index de type PATH s'avère particulièrement utile :

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  

Dans la requête, l'expression de chemin d'accès /PD:ProductDescription/@ProductModelID et sa valeur "19" se trouvant dans la méthode exist() correspondent aux champs de clé définis pour l'index de type PATH. Des recherches directes portant sur l'index PATH peuvent s'effectuer et offrir ainsi de meilleures performances que dans le cas d'une recherche séquentielle portant sur les valeurs de chemin d'accès de l'index primaire.

les index XML secondaires de type VALUE (utilisant la valeur comme critère de recherche) ;

Si des requêtes s'appuient sur les valeurs pour ses résultats, par exemple /Root/ProductDescription/@*[. = "Mountain Bike"] ou //ProductDescription[@Name = "Mountain Bike"], et que le chemin n'est pas entièrement précisé ou qu'il contient un caractère générique, vous pourriez obtenir des résultats plus rapidement en construisant un index XML secondaire sur les valeurs des nœuds de l'index XML primaire.

Les colonnes clés (correspondant aux valeurs de nœud et aux chemins d'accès) de l'index de type VALUE sont tirées de l'index XML primaire. Si vous devez lancer des requêtes sur des valeurs provenant d'instances XML sans connaître le nom des éléments ou des attributs contenant les valeurs, il se peut que l'index de type VALUE vous soit particulièrement utile. Par exemple, l'expression suivante tire parti de l'utilisation d'un index de type VALUE :

  • //author[LastName="someName"]où vous connaissez la valeur de l’élément, mais le <>authorparent peut se produire n’importe où.<LastName>

  • /book[@* = "someValue"]où la requête recherche l’élément <>bookqui a un attribut ayant la valeur "someValue".

La requête suivante renvoie ContactID à partir de la table Contact . La WHERE clause spécifie un filtre qui recherche des valeurs dans la colonne de AdditionalContactInfo``xml type. L'ID des contacts n'est renvoyé que si l'objet blob XML relatif aux informations complémentaires sur les contacts correspondants contient un numéro de téléphone spécifique. Étant donné que l’élément <telephoneNumber> peut apparaître n’importe où dans le code XML, l’expression de chemin d’accès spécifie l’axe décroissant ou 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  

Dans ce cas, la valeur de recherche est <number> connue, mais elle peut apparaître n’importe où dans le instance XML en tant qu’enfant de l’élément .<telephoneNumber> Ce type de requête pourrait être plus efficace grâce à la recherche d'une valeur précise dans les index.

Index secondaire de type PROPERTY

Les requêtes chargées d'extraire plusieurs valeurs d'instances XML distinctes peuvent bénéficier de l'utilisation d'un index de type PROPERTY. Ce scénario se produit lorsque vous récupérez des propriétés d’objet à l’aide de la méthode value() du xml type et lorsque la valeur de clé primaire de l’objet est connue.

L'index utilisant le paramètre PROPERTY se construit d'après des colonnes (PK pour la clé primaire, Path pour le chemin d'accès, ainsi que la valeur du nœud) issues de l'index XML primaire, où PK correspond à la clé primaire de la table de base.

Par exemple, concernant le modèle de produit 19, la requête suivante extrait les valeurs des attributs ProductModelID et ProductModelName grâce à la méthode value() . Contrairement aux requêtes utilisant les index XML primaires ou tout autre index XML secondaire, l'index PROPERTY peut permettre une exécution plus rapide.

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  

À l’exception des différences décrites plus loin dans cette rubrique, la création d’un index XML sur unexml colonne de type est similaire à la création d’un index sur une colonne sansxml type. Les instructions DDL Transact-SQL suivantes permettent de créer et de gérer les index XML :

Obtention d'informations sur les index XML

Les entrées d'index XML apparaissent dans l'affichage catalogue, sys.indexes, avec l'index de « type » 3. La colonne name contient le nom de l'index XML.

Les index XML sont également enregistrés dans l'affichage catalogue, sys.xml_indexes, qui contient toutes les colonnes de sys.indexes, ainsi que d'autres plus spécifiques et utiles aux index XML. La valeur NULL de la colonne, secondary_type, indique qu'il s'agit d'un index XML primaire ; les valeurs « P », « R » et « V » représentent respectivement les index XML secondaires PATH, PROPERTY et VALUE.

L’espace utilisé par les index XML figure dans la fonction table sys.dm_db_index_physical_stats, qui fournit des informations telles que le nombre de pages disque occupées, la taille moyenne des lignes en octets et le nombre d'enregistrements, pour tous les types d'index. Vous y trouvez également les index XML. Ces informations sont disponibles pour chaque partition de la base de données. Les index XML utilisent le même schéma et la même fonction de partitionnement que la table de base.

Voir aussi

sys.dm_db_index_physical_stats (Transact-SQL)
Données XML (SQL Server)