Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Otimização de desempenho XML do servidor XML


Posso dar-lhe uma resposta e um palpite:

Primeiro eu uso uma variável de tabela declarada para simular seu cenário:
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>');

--Esta consulta lerá o XML com uma conversão de uma sub-seleção . Você pode usar um CTE em vez disso, mas isso deve ser apenas açúcar sintático ...
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);

--A segunda parte usa uma tabela para escrever no XML digitado e ler a partir daí:
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);

Por que /text() mais rápido do que sem /text() ?


Se você observar meu exemplo, o conteúdo de um elemento é tudo da tag de abertura até a tag de fechamento . O text() de um elemento é o texto flutuante entre essas etiquetas. Você pode ver isso nos resultados do select acima. O text() é uma parte armazenada separadamente em uma estrutura de árvore na verdade (leia a próxima seção). Para buscá-lo, é uma ação de uma etapa . Caso contrário, uma estrutura complexa deve ser analisada para encontrar tudo entre a tag de abertura e sua tag de fechamento correspondente - mesmo que não haja nada além do text() .

Por que devo armazenar XML no tipo apropriado?


XML não é apenas texto com alguns caracteres extras bobos! É um documento com uma estrutura complexa. O XML não é armazenado como o texto que você vê . XML é armazenado em uma estrutura de árvore. Sempre que você converte uma string, que representa um XML, em um XML real, esse trabalho muito caro deve ser feito. Quando o XML é apresentado a você (ou qualquer outra saída), a string de representação é (re)construída do zero.

Por que a abordagem pré-fabricada é mais rápida


Isso é suposição...
No meu exemplo, ambas as abordagens são bastante iguais e levam a (quase) o mesmo plano de execução.
O SQL Server não funcionará da maneira que você espera. Este não é um sistema de procedimentos onde você declara faça isso, depois faça isso e depois faça isso! . Você diz ao motor o que deseja, e o motor decide como fazer isso melhor. E o mecanismo é muito bom com isso!
Antes de iniciar a execução, o mecanismo tenta estimar os custos das abordagens. CONVERT (ou CAST ) é uma operação bastante barata. Pode ser que o mecanismo decida trabalhar na lista de suas chamadas e fazer o elenco para cada necessidade única vez após vez, porque acha que isso é mais barato do que a criação cara de uma tabela derivada ...