Einfaches LÖSCHEN, aber komplizierter Ausführungsplan

9

Wenn ich dieses Löschen ausführe:

DELETE FROM ETLHeaders WHERE ETLHeaderID < 32465870

... löscht 39.157 Zeilen. Es sollte einfach sein, da es auf ETLHeaderID gelöscht wird, bei der es sich um den Clustered-Index und den Primärschlüssel handelt. Aber (gemäß dem Ausführungsplan) scheint es 361.190 Zeilen zu treffen und andere Indizes zu verwenden. Die Tabelle enthält ein Feld mit einem XML-Datentyp (falls dies DELETE betrifft).

Irgendwelche Ideen warum und wie ich dieses LÖSCHEN beschleunigen kann?

Ausführungsplan hier: http://sharetext.org/qwDY Tabellenschema hier: http://sharetext.org/Vl9j

Vielen Dank

Craig HB
quelle

Antworten:

10

Die obersten Ebenen des Plans befassen sich mit dem Entfernen von Zeilen aus der Basistabelle (dem Clustered-Index) und dem Verwalten von vier Nonclustered-Indizes. Zwei dieser Indizes werden zeilenweise verwaltet, während die Clustered-Index-Löschvorgänge verarbeitet werden. Dies sind die "+2 nicht gruppierten Indizes", die unten grün hervorgehoben sind.

Für die beiden anderen nicht gruppierten Indizes hat der Optimierer entschieden, dass es am besten ist, die Schlüssel dieser Indizes in einer temporären Arbeitstabelle (der Eager-Spool) zu speichern und dann die Spool zweimal abzuspielen, wobei nach den Indexschlüsseln sortiert wird, um ein sequentielles Zugriffsmuster zu fördern.

Regelmäßige Indexpflege

Die letzte Abfolge von Vorgängen befasst sich mit der Verwaltung der Primär- und Sekundärindizes xml, die nicht in Ihrem DDL-Skript enthalten waren:

XML-Indexpflege

Hier gibt es nicht viel zu tun. Nicht gruppierte Indizes und xmlIndizes müssen mit den Daten in der Basistabelle synchronisiert bleiben. Die Kosten für die Verwaltung solcher Indizes sind Teil des Kompromisses, den Sie beim Erstellen zusätzlicher Indizes für eine Tabelle eingehen.

xmlAllerdings sind die Indizes besonders problematisch. Für den Optimierer ist es sehr schwierig, genau zu beurteilen, wie viele Zeilen in dieser Situation qualifiziert sind. Tatsächlich wird der xmlIndex stark überschätzt , was dazu führt, dass für diese Abfrage fast 12 GB Speicher gewährt werden (obwohl zur Laufzeit nur 28 MB verwendet werden):

Geschätzte Zeilenanzahl

Sie können die Löschung in kleineren Stapeln durchführen, um die Auswirkungen der übermäßigen Speicherzuweisung zu verringern.

Sie können die Leistung eines Plans auch ohne die Sortierung testenOPTION (QUERYTRACEON 8795) . Dies ist ein undokumentiertes Trace-Flag. Sie sollten es daher nur auf einem Entwicklungs- oder Testsystem ausprobieren, niemals in der Produktion. Wenn der resultierende Plan viel schneller ist, können Sie die Plan-XML erfassen und daraus einen Planleitfaden für die Produktionsabfrage erstellen .

Paul White 9
quelle
3

Sie sind auf dem richtigen Weg - der XML-Index ist das Problem. Offensichtlich gibt es sowohl einen primären als auch einen sekundären XML-Index.

Bei einem DELETE für die Basistabelle (ETLHeaders) müssen die Daten auch aus jedem Index dieser Tabelle gelöscht werden. Dieser Overhead kann insbesondere für XML-Indizes erheblich sein.

Der Index, der die lange Dauer verursacht, ist der sekundäre XML-Index [XML_IX_ETLHeaders_Property]. Die 39.157 Zeilen in Ihrer "relationalen Tabelle" beziehen sich auf 361.190 Zeilen im primären XML-Index [XML_IX_ETLHeaders]. Und diese 361.000 Zeilen müssen sortiert werden, damit der Sekundärindex gelöscht werden kann. Und diese Sortieroperation verursacht die lange Dauer der Abfrage. (Nebenbei bemerkt, die Indexstatistik beider XML-Indizes scheint weit entfernt zu sein: Die tatsächliche Datengröße der 361.000 Zeilen des primären XML-Index beträgt 160 MB, während die geschätzte Datengröße fast 4 TB beträgt (ja, 4 TerraByte !!)) .

Die einzige Möglichkeit, diese Abfrage zu beschleunigen, besteht darin, den sekundären XML-Index zu entfernen. Abhängig von den Daten ist es möglicherweise eine bessere Option, die XML-Daten in eine relationale Tabelle zu zerlegen.

Lmu92
quelle