DELETE simple, pero plan de ejecución complicado

9

Cuando ejecuto esta eliminación:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870

... elimina 39,157 filas. Debería ser simple porque está eliminando en ETLHeaderID, que es el índice agrupado y la clave primaria. Pero (de acuerdo con el plan de ejecución) parece estar alcanzando 361,190 filas y utilizando otros índices. La tabla tiene un campo con un tipo de datos XML (en caso de que afecte este DELETE).

¿Alguna idea de por qué y cómo puedo acelerar este BORRAR?

Plan de ejecución aquí: http://sharetext.org/qwDY Esquema de tabla aquí: http://sharetext.org/Vl9j

Gracias

Craig HB
fuente

Respuestas:

10

Los niveles superiores del plan están relacionados con la eliminación de filas de la tabla base (el índice agrupado) y el mantenimiento de cuatro índices no agrupados. Dos de estos índices se mantienen fila por fila al mismo tiempo que se procesan las eliminaciones de índice agrupadas. Estos son los "+2 índices no agrupados" resaltados en verde a continuación.

Para los otros dos índices no agrupados, el optimizador ha decidido que es mejor guardar las claves de estos índices en una mesa de trabajo tempdb (el Eager Spool), luego reproducir el spool dos veces, clasificándolas por las claves del índice para promover un patrón de acceso secuencial.

Mantenimiento de índice regular

La secuencia final de operaciones se refiere al mantenimiento de los xmlíndices primario y secundario , que no se incluyeron en su secuencia de comandos DDL:

Mantenimiento de índice XML

No hay mucho que hacer al respecto. Los índices e xmlíndices no agrupados deben mantenerse sincronizados con los datos de la tabla base. El costo de mantener dichos índices es parte de la compensación que realiza al crear índices adicionales en una tabla.

Dicho esto, los xmlíndices son particularmente problemáticos. Es muy difícil para el optimizador evaluar con precisión cuántas filas calificarán en esta situación. De hecho, sobreestima enormemente el xmlíndice, lo que da como resultado que se otorguen casi 12 GB de memoria para esta consulta (aunque solo se usan 28 MB en tiempo de ejecución):

Recuento estimado de filas

Podría considerar realizar la eliminación en lotes más pequeños, con la esperanza de reducir el impacto de la concesión de memoria excesiva.

También puede probar el rendimiento de un plan sin utilizar los tipos OPTION (QUERYTRACEON 8795). Este es un indicador de rastreo no documentado, por lo que solo debe probarlo en un sistema de desarrollo o prueba, nunca en producción. Si el plan resultante es mucho más rápido, puede capturar el XML del plan y usarlo para crear una Guía del plan para la consulta de producción.

Paul White 9
fuente
3

Estás en el camino correcto: el índice XML es el problema. Obviamente, hay un índice XML primario y uno secundario.

Al realizar DELETE contra la tabla base (ETLHeaders), los datos también deben eliminarse de cada índice de esta tabla. Esta sobrecarga puede ser significativa, especialmente para los índices XML.

El índice que causa la larga duración es el índice XML secundario [XML_IX_ETLHeaders_Property]. Las 39,157 filas en su "tabla relacional" se refieren a 361,190 filas en el índice XML primario [XML_IX_ETLHeaders]. Y esas 361k filas deben ordenarse para poder usarse para eliminar el índice secundario. Y esta operación de clasificación está causando la larga duración de la consulta. (Como nota al margen, las estadísticas de índice de ambos índices xml parecen estar muy alejadas: el tamaño de datos real de las 361k filas del índice xml primario es de 160 MB, mientras que el tamaño de datos estimado es de casi 4 TB (¡sí, 4 TerraByte!)) .

La única opción que veo para acelerar esta consulta es eliminar el índice XML secundario. Dependiendo de los datos, podría ser una mejor opción para triturar los datos XML en una tabla relacional.

Lmu92
fuente