DELETE simples, mas plano de execução complicado

9

Quando executo essa exclusão:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870

... exclui 39.157 linhas. Deve ser simples porque está excluindo no ETLHeaderID, que é o índice em cluster e a chave primária. Mas (de acordo com o plano de execução), parece estar atingindo 361.190 linhas e usando outros índices. A tabela possui um campo com um tipo de dados XML (no caso que afeta esse DELETE).

Alguma idéia de por que e como posso acelerar esse DELETE?

Plano de execução aqui: http://sharetext.org/qwDY Esquema da tabela aqui: http://sharetext.org/Vl9j

obrigado

Craig HB
fonte

Respostas:

10

Os níveis mais altos do plano estão relacionados à remoção de linhas da tabela base (o índice clusterizado) e à manutenção de quatro índices não clusterizados. Dois desses índices são mantidos linha por linha ao mesmo tempo em que as exclusões de índice em cluster são processadas. Estes são os "+2 índices não agrupados" destacados em verde abaixo.

Para os outros dois índices não clusterizados, o otimizador decidiu que é melhor salvar as chaves desses índices em uma mesa de trabalho tempdb (o Eager Spool) e depois executar o spool duas vezes, classificando pelas chaves de índice para promover um padrão de acesso seqüencial.

Manutenção regular do índice

A sequência final de operações está relacionada à manutenção dos xmlíndices primário e secundário , que não foram incluídos no seu script DDL:

Manutenção de índice XML

Não há muito a ser feito sobre isso. Índices e xmlíndices não clusterizados devem ser mantidos sincronizados com os dados na tabela base. O custo de manutenção desses índices faz parte do compromisso que você faz ao criar índices extras em uma tabela.

Dito isto, os xmlíndices são particularmente problemáticos. É muito difícil para o otimizador avaliar com precisão quantas linhas se qualificarão nessa situação. De fato, ela superestima demais o xmlíndice, resultando em quase 12 GB de memória sendo concedidos para essa consulta (embora apenas 28 MB sejam usados ​​em tempo de execução):

Contagem estimada de linhas

Você pode considerar a exclusão em lotes menores, na esperança de reduzir o impacto da concessão excessiva de memória.

Você também pode testar o desempenho de um plano sem as classificações OPTION (QUERYTRACEON 8795). Este é um sinalizador de rastreamento não documentado, portanto, você deve experimentá-lo apenas em um sistema de desenvolvimento ou teste, nunca em produção. Se o plano resultante for muito mais rápido, você poderá capturar o XML do plano e usá-lo para criar um Guia de Plano para a consulta de produção.

Paul White 9
fonte
3

Você está no caminho certo - o índice XML é o problema. Obviamente, há um índice XML primário e secundário.

Ao executar um DELETE na tabela base (ETLHeaders), os dados também devem ser excluídos de todos os índices dessa tabela. Essa sobrecarga pode ser significativa, especialmente para índices XML.

O índice que causa a longa duração é o índice XML secundário [XML_IX_ETLHeaders_Property]. As 39.157 linhas na sua "tabela relacional" referem-se a 361.190 linhas no índice XML primário [XML_IX_ETLHeaders]. E essas 361k linhas precisam ser classificadas para poderem ser usadas para excluir o índice secundário. E essa operação de classificação está causando a longa duração da consulta. (Como uma observação lateral, as estatísticas do índice de ambos os índices xml parecem muito distantes: o tamanho real dos dados das 361 mil linhas do índice xml primário é de 160 MB, enquanto o tamanho estimado dos dados é de quase 4 TB (sim, 4 TerraByte !!)) .

A única opção que vejo para acelerar essa consulta é eliminar o índice XML secundário. Dependendo dos dados, pode ser uma opção melhor fragmentar os dados XML em uma tabela relacional.

Lmu92
fonte