Delen via


XML-indexen (SQL Server)

Van toepassing op:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

XML-indexen kunnen worden gemaakt voor kolommen met xml-gegevenstypen . Ze indexeren alle tags, waarden en paden over de XML-exemplaren in de kolom. Dit verbetert de queryprestaties. Uw toepassing kan in de volgende situaties profiteren van een XML-index:

  • Query's op XML-kolommen zijn gebruikelijk in uw workload. Onderhoudskosten voor XML-indexen tijdens het wijzigen van gegevens moeten worden overwogen.

  • Uw XML-waarden zijn relatief groot en de opgehaalde onderdelen zijn relatief klein. Het bouwen van de index voorkomt dat alle gegevens tijdens de uitvoeringstijd geanalyseerd moeten worden en maakt het mogelijk om te zoeken in de index voor efficiënte queryverwerking.

Vanaf SQL Server 2022 (16.x) en latere versies, en in Azure SQL Database en Azure SQL Managed Instance, kunt u XML-compressie gebruiken om XML-gegevens buiten rij te comprimeren voor zowel XML-kolommen als indexen. XML-compressie vermindert de capaciteitsvereisten voor gegevensopslag.

XML-indexen vallen in de volgende categorieën:

  • Primaire XML-index
  • Secundaire XML-index

De eerste index van de kolom xml-type moet de primaire XML-index zijn. Met behulp van de primaire XML-index worden de volgende typen secundaire indexen ondersteund: PATH, VALUE en PROPERTY. Afhankelijk van het type query's kunnen deze secundaire indexen helpen bij het verbeteren van de queryprestaties.

Opmerking

U kunt geen XML-index maken of wijzigen, tenzij de databaseopties correct zijn ingesteld voor het werken met het XML-gegevenstype . Zie Full-Text Zoeken met XML-kolommen gebruiken voor meer informatie.

XML-exemplaren worden opgeslagen in xml-typekolommen als grote binaire objecten (BLOBs). Deze XML-exemplaren kunnen groot zijn en de opgeslagen binaire weergave van exemplaren van xml-gegevenstypen kan maximaal 2 GB zijn. Zonder een index worden deze binaire grote objecten tijdens runtime versnipperd om een query te evalueren. Het versnipperen kan tijdrovend zijn. Kijk bijvoorbeeld eens naar de volgende query:

;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;

Als u de XML-exemplaren wilt selecteren die voldoen aan de voorwaarde in de WHERE component, wordt het binaire grote object (BLOB) van XML in elke rij van de tabel Production.ProductModel tijdens runtime versnipperd. Vervolgens wordt de expressie (/PD:ProductDescription/@ProductModelID[.="19"]) in de exist() methode geëvalueerd. Deze run-time-shredding kan duur zijn, afhankelijk van de grootte en het aantal exemplaren dat in de kolom is opgeslagen.

Als het uitvoeren van query's op binaire grote xml-objecten (BLOBs) gebruikelijk is in uw toepassingsomgeving, kunt u hiermee de xml-typekolommen indexeren. Er zijn echter kosten verbonden aan het onderhouden van de index tijdens het wijzigen van gegevens.

Primaire XML-index

De primaire XML-index indexeert alle tags, waarden en paden in de XML-exemplaren in een XML-kolom. Als u een primaire XML-index wilt maken, moet de tabel waarin de XML-kolom zich voordoet een geclusterde index hebben op de primaire sleutel van de tabel. SQL Server gebruikt deze primaire sleutel om rijen in de primaire XML-index te correleren met rijen in de tabel die de XML-kolom bevat.

De primaire XML-index is een versnipperde en persistente weergave van de XML-BLObs in de kolom xml-gegevenstype . Voor elk binair groot object (BLOB) in de kolom maakt de index verschillende rijen met gegevens. Het aantal rijen in de index is ongeveer gelijk aan het aantal knooppunten in het binaire grote XML-object. Wanneer een query het volledige XML-exemplaar ophaalt, levert SQL Server het exemplaar uit de XML-kolom. Query's binnen XML-exemplaren maken gebruik van de primaire XML-index en kunnen scalaire waarden of XML-substructuren retourneren met behulp van de index zelf.

In elke rij worden de volgende knooppuntgegevens opgeslagen:

  • Tagnaam, zoals een element of kenmerknaam.

  • Knooppuntwaarde.

  • Knooppunttype, zoals een elementknooppunt, kenmerkknooppunt of tekstknooppunt.

  • Documentordergegevens, vertegenwoordigd door een interne knooppunt-id.

  • Pad van elk knooppunt naar de wortel van de XML-structuur. In deze kolom wordt gezocht naar padexpressies in de query.

  • Primaire sleutel van de basistabel. De primaire sleutel van de basistabel wordt gedupliceerd in de primaire XML-index voor een back-join met de basistabel en het maximum aantal kolommen in de primaire sleutel van de basistabel is beperkt tot 15.

Deze knooppuntinformatie wordt gebruikt om XML-resultaten voor een opgegeven query te evalueren en samen te stellen. Voor optimalisatiedoeleinden worden de tagnaam en de gegevens van het knooppunttype gecodeerd als geheel getalwaarden en gebruikt de kolom Path dezelfde codering. Paden worden ook in omgekeerde volgorde opgeslagen om overeenkomende paden toe te staan wanneer alleen het padachtervoegsel bekend is. Voorbeeld:

  • //ContactRecord/PhoneNumber waarbij alleen de laatste twee stappen bekend zijn

OF

  • /Book/*/Title waarbij het jokerteken * in het midden van de expressie wordt opgegeven.

De queryprocessor maakt gebruik van de primaire XML-index voor query's die betrekking hebben op xml-gegevenstypemethoden en retourneert scalaire waarden of de XML-substructuren van de primaire index zelf. (In deze index worden alle benodigde gegevens opgeslagen om het XML-exemplaar te reconstrueren.)

De volgende query retourneert bijvoorbeeld samenvattingsgegevens die zijn opgeslagen in de CatalogDescription kolom xml-type in de ProductModel tabel. De query retourneert <Summary> alleen informatie voor productmodellen waarvan de catalogusbeschrijving ook de <Features> beschrijving opslaat.

;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/PD:Features') = 1

Met betrekking tot de primaire XML-index worden, in plaats van elk binair groot XML-objectexemplaar in de basistabel op te delen, de rijen in de index die overeenkomen met elk binair groot XML-object opeenvolgend doorzocht voor de expressie die is opgegeven in de exist()-methode. Als het pad wordt gevonden in de kolom Pad in de index, wordt het element samen met de <Summary> bijbehorende substructuren opgehaald uit de primaire XML-index en geconverteerd naar een binair groot XML-object als resultaat van de query() methode.

De primaire XML-index wordt niet gebruikt bij het ophalen van een volledig XML-exemplaar. Met de volgende query wordt bijvoorbeeld opgehaald uit de tabel het hele XML-exemplaar dat de productie-instructies voor een specifiek productmodel beschrijft.

USE AdventureWorks2022;

SELECT Instructions
FROM   Production.ProductModel
WHERE  ProductModelID = 7;

Secundaire XML-indexen

Als u de zoekprestaties wilt verbeteren, kunt u secundaire XML-indexen maken. Er moet eerst een primaire XML-index bestaan voordat u secundaire indexen kunt maken. Dit zijn de typen:

  • Secundaire XML-index PATH

  • WAARDE secundaire XML-index

  • EIGENSCHAP secundaire XML-index

Hieronder volgen enkele richtlijnen voor het maken van een of meer secundaire indexen:

  • Als uw werklast padexpressies aanzienlijk gebruikt voor XML-kolommen, zal de secundaire XML-padindex waarschijnlijk uw werklast versnellen. Het meest voorkomende geval is het gebruik van de exist() methode voor XML-kolommen in de WHERE-component van Transact-SQL.

  • Als uw workload meerdere waarden ophaalt uit afzonderlijke XML-exemplaren met behulp van padexpressies, kan het clusteren van paden binnen elk XML-exemplaar in de eigenschapsindex nuttig zijn. Dit scenario treedt meestal op in een eigenschap-pakket scenario, waarin eigenschappen van een object worden opgehaald en de bijbehorende sleutelwaarde bekend is.

  • Als uw werkbelasting betrekking heeft op het uitvoeren van query's op waarden in XML-exemplaren zonder het element of de kenmerknamen te kennen die deze waarden bevatten, kunt u de WAARDE-index maken. Dit gebeurt meestal bij afstammingsas-opzoekacties, zoals //author[last-name="Howard"], waarbij <author> elementen op elk niveau binnen de hiërarchie kunnen voorkomen. Het gebeurt ook in jokertekenquery's, zoals /book [@* = "novel"], waarbij de query zoekt naar <book> elementen met een kenmerk met de waarde "novel".

Secundaire XML-index PATH

Als uw query's over het algemeen padexpressies opgeven voor xml-typekolommen , kan een secundaire PATH-index de zoekopdracht versnellen. Zoals eerder in dit artikel is beschreven, is de primaire index handig wanneer u query's hebt die de methode opgeven exist() in de WHERE-component. Als u een secundaire PATH-index toevoegt, kunt u ook de zoekprestaties in dergelijke query's verbeteren.

Hoewel een primaire XML-index vermijdt om de binaire grote XML-objecten tijdens runtime te versnipperen, biedt deze mogelijk niet de beste prestaties voor query's op basis van padexpressies. Omdat alle rijen in de primaire XML-index die overeenkomen met een binair groot XML-object opeenvolgend worden doorzocht voor grote XML-exemplaren, kan de sequentiële zoekopdracht traag zijn. In dit geval kan een secundaire index die is gebaseerd op de padwaarden en knooppuntwaarden in de primaire index aanzienlijk sneller zoeken. In de secundaire PATH-index zijn het pad- en knooppuntwaarden belangrijke kolommen waarmee efficiënter wordt gezocht bij het zoeken naar paden. De queryoptimalisatie kan de PATH-index gebruiken voor expressies zoals de expressies die worden weergegeven in het volgende:

  • /root/Location waarmee alleen een pad wordt opgegeven

OF

  • /root/Location/@LocationID[.="10"] waarbij zowel het pad als de knooppuntwaarde zijn opgegeven.

In de volgende query ziet u waar de PATH-index nuttig is:

;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;

In de query komen de padexpressie /PD:ProductDescription/@ProductModelID en waarde "19" in de exist() methode overeen met de sleutelvelden van de PATH-index. Dit maakt direct zoeken in de PATH-index mogelijk en biedt betere zoekprestaties dan de sequentiële zoekopdracht naar padwaarden in de primaire index.

WAARDE secundaire XML-index

Als query's bijvoorbeeld /Root/ProductDescription/@*[. = "Mountain Bike"] zijn gebaseerd op waarden of //ProductDescription[@Name = "Mountain Bike"]als het pad niet volledig is opgegeven of als het een jokerteken bevat, kunt u snellere resultaten verkrijgen door een secundaire XML-index te bouwen die is gebouwd op knooppuntwaarden in de primaire XML-index.

De belangrijkste kolommen van de WAARDE-index zijn (knooppuntwaarde en pad) van de primaire XML-index. Als uw workload query's uitvoert op waarden uit XML-exemplaren zonder het element of de kenmerknamen te kennen die de waarden bevatten, kan een WAARDE-index nuttig zijn. De volgende expressie profiteert bijvoorbeeld van een WAARDE-index:

  • //author[LastName="someName"] waar u de waarde van het <LastName> element weet, maar waar het <author> bovenliggende element zich overal kan voordoen.

  • /book[@* = "someValue"] waarbij de query zoekt naar het <book> element met een kenmerk met de waarde "someValue".

De volgende query retourneert ContactID uit de Contact tabel. De WHERE component geeft een filter op dat zoekt naar waarden in de AdditionalContactInfo kolom xml-type. De contact-id's worden alleen geretourneerd als het overeenkomstige binaire XML-object met aanvullende contactgegevens een specifiek telefoonnummer bevat. Omdat het telephoneNumber element ergens in de XML kan worden weergegeven, geeft de padexpressie de aflopende of zelfas aan.

;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;

In deze situatie is de zoekwaarde voor <number> bekend, maar deze kan overal in het XML-exemplaar als een kind van het telephoneNumber-element verschijnen. Dit type query kan profiteren van een indexzoekactie op basis van een specifieke waarde.

Secundaire eigenschapsindex

Query's die een of meer waarden ophalen uit afzonderlijke XML-exemplaren, kunnen profiteren van een EIGENSCHAPsindex. Dit scenario treedt op wanneer u objecteigenschappen ophaalt met behulp van de value() methode van het XML-type en wanneer de primaire sleutelwaarde van het object bekend is.

De EIGENSCHAPsindex is gebaseerd op kolommen (PK, pad en knooppuntwaarde) van de primaire XML-index waarbij PK de primaire sleutel van de basistabel is.

Voor het productmodel 19haalt de volgende query bijvoorbeeld de ProductModelID en ProductModelName kenmerkwaarden op met behulp van de value() methode. In plaats van de primaire XML-index of de andere secundaire XML-indexen te gebruiken, kan de EIGENSCHAPsindex sneller worden uitgevoerd.

;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;

Met uitzondering van de verschillen die verderop in dit artikel worden beschreven, is het maken van een XML-index voor een kolom van een XML-type vergelijkbaar met het maken van een index voor een niet-XML-typekolom . De volgende Transact-SQL DDL-instructies kunnen worden gebruikt voor het maken en beheren van XML-indexen:

XML-compressie

van toepassing op: SQL Server 2022 (16.x) en latere versies, Azure SQL Database en Azure SQL Managed Instance.

Als u XML-compressie inschakelt, wordt de fysieke opslagindeling gewijzigd van de gegevens die zijn gekoppeld aan het XML-gegevenstype in een gecomprimeerde binaire indeling, maar worden de syntaxis of semantiek van XML-gegevens niet gewijzigd. Toepassingswijzigingen zijn niet vereist wanneer een of meer tabellen zijn ingeschakeld voor XML-compressie.

Alleen het XML-gegevenstype wordt beïnvloed door XML-compressie. XML-gegevens worden gecomprimeerd met het Xpress-compressie-algoritme. Bestaande XML-indexen worden gecomprimeerd met gegevenscompressie. Gegevenscompressie wordt intern ingeschakeld voor XML-indexen wanneer XML-compressie is ingeschakeld.

XML-compressie kan naast gegevenscompressie in dezelfde tabellen worden ingeschakeld.

XML-indexen nemen de compressie-eigenschap van de tabel niet over. Als u indexen wilt comprimeren, moet u XML-compressie expliciet inschakelen voor XML-indexen.

Secundaire XML-indexen nemen de compressie-eigenschap van de primaire XML-index niet over.

Standaard is de instelling voor XML-compressie voor XML-indexen ingesteld op UIT wanneer de index wordt gemaakt.

Informatie over XML-indexen ophalen

XML-indexvermeldingen worden weergegeven in de catalogusweergave sys.indexes met de index type van 3. De naamkolom bevat de naam van de XML-index.

XML-indexen worden ook vastgelegd in de catalogusweergave sys.xml_indexes. Dit bevat alle kolommen van sys.indexes en enkele specifieke kolommen die nuttig zijn voor XML-indexen. De waarde NULL in de kolom secondary_type geeft een primaire XML-index aan; de waarden PR en V staan voor secundaire XML-indexen PATH, PROPERTY en VALUE.

Het ruimtegebruik van XML-indexen vindt u in de tabelwaardefunctie sys.dm_db_index_physical_stats. Het bevat informatie, zoals het aantal gegevenspagina's dat wordt bezet, de gemiddelde rijgrootte in bytes en het aantal records voor alle indextypen. Dit omvat ook XML-indexen. Deze informatie is beschikbaar voor elke databasepartitie. XML-indexen maken gebruik van hetzelfde partitioneringsschema en dezelfde partitioneringsfunctie van de basistabel.

Volgende stappen