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

Optymalizacja wydajności XML serwera XML

Mogę dać Ci jedną odpowiedź i jedno zgadnięcie:

Najpierw używam zadeklarowanej zmiennej tabeli do makietowania Twój scenariusz:

DECLARE @tbl TABLE(s NVARCHAR(MAX));
INSERT INTO @tbl VALUES
(N'<root>
    <SomeElement>This is first text of element1
        <InnerElement>This is text of inner element1</InnerElement>
        This is second text of element1
    </SomeElement>
    <SomeElement>This is first text of element2
        <InnerElement>This is text of inner element2</InnerElement>
        This is second text of element2
    </SomeElement>
</root>')
,(N'<root>
    <SomeElement>This is first text of elementA
        <InnerElement>This is text of inner elementA</InnerElement>
        This is second text of elementA
    </SomeElement>
    <SomeElement>This is first text of elementB
        <InnerElement>This is text of inner elementB</InnerElement>
        This is second text of elementB
    </SomeElement>
</root>');

– To zapytanie odczyta kod XML z rzutowaniem z podwyboru . Możesz użyć CTE zamiast tego, ale powinien to być tylko cukier syntaktyczny...

SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
      ,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
      ,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
      ,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM (SELECT CAST(s AS XML) FROM @tbl) AS tbl(TheXml)
CROSS APPLY TheXml.nodes(N'/root/SomeElement') AS A(se);

--Druga część używa tabeli do pisania we wpisywanym pliku XML i odczytywania z niego:

DECLARE @tbl2 TABLE(x XML)
INSERT INTO @tbl2
SELECT CAST(s AS XML) FROM @tbl;

SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
      ,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
      ,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
      ,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM @tbl2 t2
CROSS APPLY t2.x.nodes(N'/root/SomeElement') AS A(se);

Dlaczego /text() szybciej niż bez /text() ?

Jeśli spojrzysz na mój przykład, zawartość elementu to wszystko od tagu otwierającego do tagu zamykającego . text() elementu to tekst pływający między tymi znacznikami. Możesz to zobaczyć w wynikach wyboru powyżej. text() to jedna oddzielnie przechowywana część w strukturze drzewa faktycznie (przeczytaj następną sekcję). Pobranie go to jednoetapowe działanie . W przeciwnym razie złożona struktura musi zostać przeanalizowana, aby znaleźć wszystko między znacznikiem otwierającym a odpowiadającym mu znacznikiem zamykającym - nawet jeśli nie ma nic poza text() .

Dlaczego powinienem przechowywać XML w odpowiednim typie?

XML to nie tylko tekst z dodatkowymi, głupimi znakami! Jest to dokument o złożonej strukturze. XML nie jest przechowywany jako tekst, który widzisz . XML jest przechowywany w strukturze drzewa. Za każdym razem, gdy rzutujesz łańcuch, który reprezentuje XML, na rzeczywisty XML, ta bardzo kosztowna praca musi zostać wykonana. Kiedy XML jest prezentowany Tobie (lub innym wynikom), reprezentujący ciąg jest (od)budowany od podstaw.

Dlaczego prefabrykowane podejście jest szybsze

To jest zgadywanie...
W moim przykładzie oba podejścia są dość równe i prowadzą do (prawie) tego samego planu wykonania.
SQL Server nie będzie działał we wszystkim tak, jak można by się tego spodziewać. To nie jest system proceduralny, w którym mówisz zrób to, potem zrób to, a potem zrób to! . Mówisz silnikowi, czego chcesz, a silnik decyduje, jak zrobić to najlepiej. A silnik jest w tym całkiem niezły!
Przed rozpoczęciem wykonywania silnik próbuje oszacować koszty podejść. CONVERT (lub CAST ) jest dość tanią operacją. Może się zdarzyć, że silnik zdecyduje się opracować listę twoich wywołań i wykonać rzutowanie dla każdej potrzeby w kółko, ponieważ uważa, że ​​jest to tańsze niż kosztowne tworzenie tabeli pochodnej...




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Utwórz zadanie agenta serwera SQL za pomocą programu SSMS

  2. Zmodyfikuj ograniczenie CHECK w programie SQL Server za pomocą T-SQL

  3. Kiedy używać indeksów klastrowych lub nieklastrowych w programie SQL Server

  4. Jak opróżnić bufor PRINT w TSQL?

  5. Korzystanie z krotek w klauzuli SQL IN