sql >> Database teknologi >  >> RDS >> Sqlserver

kryds anvende xml-forespørgsel klarer sig eksponentielt dårligere, efterhånden som xml-dokumentet vokser

Hvad får krydsanvendelsesforespørgslen til at fungere så dårligt på dette simple XML-dokument og udføre eksponentielt langsommere, efterhånden som datasættet vokser?

Det er brugen af ​​den overordnede akse til at hente attribut-id'et fra vareknuden.

Det er denne del af forespørgselsplanen, der er problematisk.

Læg mærke til de 423 rækker, der kommer ud af den nederste tabelværdi-funktion.

Tilføjelse af blot en vareknude mere med tre feltnoder giver dig dette.

732 rækker returneret.

Hvad hvis vi fordobler noderne fra den første forespørgsel til i alt 6 varenoder?

Vi er oppe på hele 1602 rækker returneret.

Figuren 18 i den øverste funktion er alle feltnoder i din XML. Vi har her 6 varer med tre felter i hver vare. Disse 18 noder bruges i en indlejret sløjfe sammen med den anden funktion, så 18 udførelser, der returnerer 1602 rækker, giver, at den returnerer 89 rækker pr. iteration. Det er tilfældigvis det nøjagtige antal noder i hele XML. Nå det er faktisk en mere end alle de synlige noder. Jeg ved ikke hvorfor. Du kan bruge denne forespørgsel til at kontrollere det samlede antal noder i din XML.

select count(*)
from @XML.nodes('//*, //@*, //*/text()') as T(X)  

Altså den algoritme, der bruges af SQL Server til at få værdien, når du bruger den overordnede akse .. i en værdifunktion er, at den først finder alle de noder, du makulerer på, 18 i det sidste tilfælde. For hver af disse noder makulerer og returnerer hele XML-dokumentet og tjekker filteroperatoren for den node, du rent faktisk ønsker. Der har du din eksponentielle vækst. I stedet for at bruge den overordnede akse skal du bruge et ekstra kryds. Makuler først på emne og derefter på felt.

select I.X.value('@name', 'varchar(5)') as item_name,
       F.X.value('@id', 'uniqueidentifier') as field_id,
       F.X.value('@type', 'int') as field_type,
       F.X.value('text()[1]', 'nvarchar(15)') as field_value
from #temp as T
  cross apply T.x.nodes('/data/item') as I(X)
  cross apply I.X.nodes('field') as F(X)

Jeg har også ændret, hvordan du får adgang til feltets tekstværdi. Bruger . vil få SQL Server til at søge efter underordnede noder til field og sammenkæde disse værdier i resultatet. Du har ingen underordnede værdier, så resultatet er det samme, men det er en god ting at undgå at have den del i forespørgselsplanen (UDX-operatøren).

Forespørgselsplanen har ikke problemet med den overordnede akse, hvis du bruger et XML-indeks, men du vil stadig drage fordel af at ændre, hvordan du henter feltværdien.



  1. Vælg Top 10 Records for hver kategori i MySQL

  2. Hvordan kortlægges input- og outputkolonner dynamisk i SSIS?

  3. Hvordan tilføjer man et specifikt antal tomme rækker i sqlite?

  4. Rails-rapporter kan ikke finde en kolonne, der er der