Diferenças entre linhas estimadas e reais (reais muito menores que as estimadas) - classificação

8

Estou executando uma consulta que está processando alguns nós de um documento XML. Meu custo estimado de subárvore está na casa dos milhões e parece que tudo vem de uma operação de classificação que o servidor sql está executando em alguns dados extraídos de colunas xml via XPath. A operação de classificação tem um número estimado de linhas em torno de 19 milhões, enquanto a contagem real de linhas é de cerca de 800. A consulta em si é razoavelmente boa (1 a 2 segundos), mas a discrepância me faz pensar sobre o desempenho da consulta e por que isso diferença é tão grande?

Peter Smith
fonte
2
Isso possivelmente ocorre devido a estatísticas desatualizadas, mas é realmente impossível saber sem mais informações (incluindo a estrutura / índices da tabela, a consulta e um plano de execução real - não estimado -).
Aaron Bertrand
11
De acordo com minha experiência, os planos de consulta que envolvem trituração de XML sempre têm estimativas de custo inflacionadas. Por exemplo, ao ponto de que, se a consulta tiver um bom desempenho em termos de tempo de execução, simplesmente ignoro os números do cálculo de custos. Não faço ideia do porquê disso, mas pode ter algo a ver com o desconhecimento de quanto XML será usado como entrada. Porém, se seu objetivo é melhorar o desempenho da consulta, uma maneira que descobri é usar coleções de esquemas XML, como escrevi aqui .
Jon Seigel

Respostas:

9

Não há estatísticas geradas nas colunas XML. As estimativas são calculadas com base nas expressões usadas ao consultar o XML.

Usando esta tabela:

create table T(XMLCol xml not null)
insert into T values('<root><item value = "1" /></root>')

E essa consulta XML bastante simples:

select X.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root/item') as X(N)

Fornecerá uma linha retornada, mas as linhas estimadas retornadas serão 200. Serão 200, independentemente de qual XML ou de quanto XML você inserir na coluna XML dessa linha.

Este é o plano de consulta com a contagem estimada de linhas exibida.

insira a descrição da imagem aqui

Uma maneira de melhorar, ou pelo menos alterar, as estimativas é fornecer ao otimizador de consulta mais informações sobre o XML. Nesse caso, como sei que rootrealmente é um nó raiz no XML, posso reescrever a consulta dessa maneira.

select X2.N.value('@value', 'int')
from T
  cross apply T.XMLCol.nodes('root[1]') as X1(N)
  cross apply X1.N.nodes('item') X2(N)

Isso me dará uma estimativa de 5 linhas retornadas.

insira a descrição da imagem aqui

A reescrita da consulta provavelmente não acelerará a fragmentação do XML, mas se as estimativas forem melhores, é provável que o otimizador de consulta possa tomar decisões mais inteligentes para o restante da consulta.

Não encontrei nenhuma documentação sobre quais são as regras para as estimativas, exceto uma apresentação de Michael Rys, onde ele diz:

A estimativa de cardinalidade base é sempre 10.000 linhas!
Algum ajuste baseado em filtros de caminho empurrado

Mikael Eriksson
fonte