Suppression simple, mais plan d'exécution compliqué

9

Lorsque j'exécute cette suppression:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870

... il supprime 39157 lignes. Cela devrait être simple car il supprime sur ETLHeaderID qui est l'index cluster et la clé primaire. Mais (selon le plan d'exécution), il semble frapper 361 190 lignes et utiliser d'autres index. La table possède un champ avec un type de données XML (dans le cas où cela affecte ce SUPPRIMER).

Des idées pourquoi et comment je peux accélérer ce SUPPRIMER?

Plan d'exécution ici: http://sharetext.org/qwDY Schéma de table ici: http://sharetext.org/Vl9j

Merci

Craig HB
la source

Réponses:

10

Les niveaux supérieurs du plan concernent la suppression de lignes de la table de base (l'index cluster) et la conservation de quatre index non cluster. Deux de ces index sont conservés ligne par ligne en même temps que les suppressions d'index cluster sont traitées. Ce sont les "+2 index non clusterisés" surlignés en vert ci-dessous.

Pour les deux autres index non clusterisés, l'optimiseur a décidé qu'il est préférable d'enregistrer les clés de ces index dans une table de travail tempdb (le Eager Spool), puis de lire le spool deux fois, en le triant par les clés d'index pour promouvoir un modèle d'accès séquentiel.

Maintenance régulière de l'index

La séquence finale des opérations concerne la maintenance des xmlindex primaire et secondaire , qui n'étaient pas inclus dans votre script DDL:

Maintenance des index XML

Il n'y a pas grand-chose à faire à ce sujet. Les index non indexés et les xmlindex doivent être synchronisés avec les données de la table de base. Le coût de la maintenance de ces index fait partie du compromis que vous faites lors de la création d'index supplémentaires sur une table.

Cela dit, les xmlindices sont particulièrement problématiques. Il est très difficile pour l'optimiseur d'évaluer avec précision le nombre de lignes qui se qualifieront dans cette situation. En fait, il surestime énormément l' xmlindex, ce qui entraîne l'octroi de près de 12 Go de mémoire pour cette requête (bien que seulement 28 Mo soient utilisés au moment de l'exécution):

Nombre de lignes estimé

Vous pouvez envisager d'effectuer la suppression par lots plus petits, dans l'espoir de réduire l'impact de l'allocation de mémoire excessive.

Vous pouvez également tester les performances d'un plan sans utiliser les tris OPTION (QUERYTRACEON 8795). Il s'agit d'un indicateur de trace non documenté , vous ne devez donc l'essayer que sur un système de développement ou de test, jamais en production. Si le plan résultant est beaucoup plus rapide, vous pouvez capturer le XML du plan et l'utiliser pour créer un guide de plan pour la requête de production.

Paul White 9
la source
3

Vous êtes sur la bonne voie - l'index XML est le problème. De toute évidence, il existe un index XML primaire et secondaire.

Lorsque vous effectuez une suppression sur la table de base (ETLHeaders), les données doivent également être supprimées de chaque index de cette table. Cette surcharge peut être importante, en particulier pour les index XML.

L'index à l'origine de la longue durée est l'index XML secondaire [XML_IX_ETLHeaders_Property]. Les 39 157 lignes de votre "table relationnelle" font référence à 361 190 lignes dans l'index XML principal [XML_IX_ETLHeaders]. Et ces 361k lignes doivent être triées afin de pouvoir être utilisées pour supprimer l'index secondaire. Et cette opération de tri entraîne la longue durée de la requête. (En guise de remarque, les statistiques d'index des deux index xml semblent être très éloignées: la taille réelle des données des 361k lignes de l'index xml principal est de 160 Mo alors que la taille estimée des données est de près de 4 To (oui, 4 TerraByte !!)) .

La seule option que je vois pour accélérer cette requête est d'éliminer l'index XML secondaire. Selon les données, il peut être préférable de déchiqueter les données XML dans une table relationnelle.

Lmu92
la source