Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

krzyżowe zapytanie xml działa wykładniczo gorzej wraz ze wzrostem dokumentu xml

Co sprawia, że ​​zapytanie z zastosowaniem krzyżowym działa tak słabo na tym prostym dokumencie XML i działa wykładniczo wolniej wraz ze wzrostem zestawu danych?

Jest to użycie osi nadrzędnej do uzyskania identyfikatora atrybutu z węzła elementu.

To ta część planu zapytań jest problematyczna.

Zwróć uwagę na 423 wiersze wychodzące z niższej funkcji o wartościach w tabeli.

Dodanie jeszcze jednego węzła pozycji z trzema węzłami pól daje to.

Zwrócono 732 wierszy.

Co się stanie, jeśli podwoimy węzły z pierwszego zapytania do łącznie 6 węzłów pozycji?

Zwróciliśmy aż 1602 wierszy.

Cyfra 18 w górnej funkcji to wszystkie węzły pól w Twoim XML. Mamy tutaj 6 pozycji z trzema polami w każdej pozycji. Tych 18 węzłów jest używanych w zagnieżdżonych pętlach sprzężonych z inną funkcją, więc 18 wykonań zwracających 1602 wiersze oznacza, że ​​zwraca 89 wierszy na iterację. Tak się składa, że ​​jest to dokładna liczba węzłów w całym XML. Cóż, w rzeczywistości jest to jeden więcej niż wszystkie widoczne węzły. Nie wiem dlaczego. Możesz użyć tego zapytania, aby sprawdzić całkowitą liczbę węzłów w swoim pliku XML.

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

Tak więc algorytm używany przez SQL Server do pobierania wartości, gdy używasz osi nadrzędnej .. w funkcji wartości jest to, że najpierw znajduje wszystkie węzły, na których niszczysz, 18 w ostatnim przypadku. Dla każdego z tych węzłów niszczy i zwraca cały dokument XML i sprawdza operator filtru dla węzła, którego faktycznie potrzebujesz. Tutaj masz swój wykładniczy wzrost. Zamiast korzystać z osi rodzicielskiej, powinieneś zastosować jeden dodatkowy krzyżyk. Najpierw niszcz przedmiot, a potem pole.

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)

Zmieniłem również sposób dostępu do wartości tekstowej pola. Używając . sprawi, że SQL Server będzie szukał węzłów podrzędnych w field i połącz te wartości w wyniku. Nie masz wartości podrzędnych, więc wynik jest taki sam, ale dobrze jest unikać umieszczania tej części w planie zapytania (operator UDX).

Plan zapytania nie ma problemu z osią nadrzędną, jeśli używasz indeksu XML, ale nadal będziesz korzystać ze zmiany sposobu pobierania wartości pola.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Połącz się z bazą danych MSSQL za pomocą Flask-SQLAlchemy

  2. Utwórz tabelę partycjonowaną w SQL Server (T-SQL)

  3. Problem z tabelą tymczasową RODBC podczas łączenia się z MS SQL Server

  4. Jak usunąć pierwsze 1000 wierszy z tabeli za pomocą SQL Server 2008?

  5. SQL Server:Wyodrębnij metadane tabeli (opis, pola i ich typy danych)