CXPACKET Wartet auf die Leistungsoptimierung für SQL Server 2008


7

Ich habe eine SQL Server 2008-Abfrage, die an Millionen von Datensätzen arbeitet. Die Abfrage befindet sich in einem Prozess, der jeden Abend von einem Job ausgeführt wird. Die Abfrage kann einen ganzen Tag dauern, wenn ich sie zum ersten Mal auf den Server stelle, aber innerhalb einer Woche oder so wird sie auf weniger als eine Stunde reduziert - ohne dass ich eingreifen muss. Es repariert sich irgendwie.

Die Abfrage wird in tempdb ausgeführt, und bevor sie sich selbst behebt, stelle ich beim Überprüfen der Leistungsstatistiken Folgendes fest: CXPACKET: 20.700 Sekunden oder 66% der Wartezeit.
PAGEIOLATCH: _SH 2.500 oder 8% der Wartezeit.
LOGBUFFER: 1500 Sekunden oder 5% der Wartezeit IO_COMPLETION: 1500 Sekunden oder 5% der Wartezeit

Ich habe versucht, Indizes usw. zu optimieren, und die obigen Statistiken sind eine Verbesserung gegenüber meinem ersten Lauf, als CXPACKET 77% der Wartezeit betrug. Ich habe Tipps zur Fehlerbehebung gelesen, die besagten, dass ich meine Tempdb für jede CPU in eine Datei aufteilen sollte. Ich habe ein 32-Bit-W2K8-System mit zwei CPUs und habe Tempdb in zwei Dateien aufgeteilt und die Größe von jeweils auf 150 GB pro 10% Autogrow stark erhöht, aber sie wachsen nicht, sodass ich denke, dass die Größe ausreichend ist.

Als ich mir den Server ansah, während die Abfrage ausgeführt wurde, konnte ich feststellen, dass die CPUs NICHT fixiert waren und etwa <10% ihrer Kapazität ausmachten. Was angeheftet wurde, war DISK IO. Die Maschine hat eine einzelne Festplatte.

Hier sind ohne weiteres die beiden Abfragen, die das Problem verursachen (die erste Abfrage war früher eine Unterabfrage der letzteren - siehe Erklärung unten):

insert into #ttcbm(tradeId1, tradeId2)
select distinct tp.tradeid tradeId1, tp1.tradeid tradeId2
from #tradeP tp
join #tradeP tp1    
on tp.cmbId = tp1.cmbId
and tp.qs_plyrid = tp1.qs_plyrid    
and tp.tradeId > tp1.tradeId    
OPTION (MAXDOP 1)


insert into #mergeT(tradeId1, tradeId2)
select distinct tp.tradeid tradeId1, tp1.tradeid tradeId2
from #tradep tp
join #tradep tp1
on tp.cmbId = tp1.cmbId
and tp.tradeid > tp1.tradeId
left join #ttcbm x
on tp.tradeId = x.tradeId1
and tp1.tradeId = x.tradeId2
where 1 = 1
and x.tradeId1 is null
and x.tradeId2 is null
OPTION (MAXDOP 1);

Ich habe MAXDOP 1 pro Tipp zur Fehlerbehebung hinzugefügt, den ich gelesen habe, dass CXPACKET durch Parallelität verursacht wurde, und vielleicht hat es mir geholfen, meine Wartezeiten ein wenig zu verkürzen, aber nicht wie die Verbesserung, die auftritt, wenn sich die Abfrage selbst behebt, dh von 24 Stunden bis zum Ende als 1 Std.

Die Tabelle #ttcbm hat eine PK von tradeid1, tradeid2 und #tradep hat eine pk von (cmbId, qs_plyrid, tradeid) und beide Tabellen haben Datensatzzahlen in der Größenordnung von 100K bis 500k. #ttcbm war früher eine Unterabfrage der letzteren Abfrage "In #mergeT einfügen", aber ich habe sie getrennt, als ich las, dass das Trennen komplizierter Abfragen die Leistung verbessern kann, wenn Parallelität ein Problem darstellt.


Datengröße? RAM-Größe? Wenn Sie "2 CPU" sagen, wie viele Sockel, Kerne sind das, und haben Sie Hyperthreading?
Gbn

@gbn. Es ist ein Vostro 420 Tower Desktop, 4 GB RAM, Intel Core 2 Duo, es hat Dual Core und, nehme ich an, 2 Sockel, aber bei letzterem bin ich mir nicht sicher. en.wikipedia.org/wiki/Intel_Core_2 Die Dell - Spezifikationen erwähnen nichts über Hyper - Threading , damit ich es annehmen , ist nicht support.dell.com/support/edocs/systems/vos220/en/sqrg/... Ich bin nicht sicher Was meinst du mit 'Größe der Daten', aber ich denke du meinst die Anzahl der Datensätze in den Tabellen #tradep und #ttcbm?
atommc

ja, Größe der Daten
gbn

Die # Tradep-Tabelle hat ~ 4,5 Millionen Datensätze
am

1
@atommc dual cpu 32 bit W2K8Zeit für ein Upgrade auf 64Bit. Haben Sie auch / 3GB Switch zusammen mit AWE aktiviert?
Kin Shah

Antworten:


10

Es gibt viele Missverständnisse über CXPACKET. CXPACKET ist nicht die Ursache Ihrer Probleme, sondern eine Nebenwirkung. Was CXPACKET bedeutet, wenn Sie sehen, dass dieser Thread einer parallelen Abfrage darauf wartet, dass ein anderer Thread dieser Abfrage etwas unternimmt. Nur weil Sie sehen, dass viele CXPACKET-Wartezeiten auftreten, bedeutet dies nicht, dass es ein Problem mit der Abfrage gibt, sondern dass es irgendwo anders ein Problem gibt. Wenn Sie sehen, dass CXPACKET wartet, müssen Sie sich die anderen Threads der SPID ansehen und sehen, welche anderen Wartezeiten neben CXPACKET bestehen. Das andere Warten ist das Problem.

Für Ihr spezielles Problem liegt der Grund dafür, dass die Laufzeit so verrückt ist, wahrscheinlich darin, dass der SQL Server an einigen Tagen einen anderen Plan generiert, weil die Statistiken nicht mehr aktuell sind (wodurch der Job lange ausgeführt wird). Dann aktualisieren Sie entweder die Statistiken manuell (oder über einen Job) oder es werden automatische Statistiken gestartet. Dann wird der Plan besser und der Job wird schnell wieder ausgeführt.

Sobald Sie das Statistikproblem gelöst haben, können Sie nach anderen Gründen suchen, warum der Job langsam ausgeführt wird. Die Tatsache, dass Sie nur eine einzige Festplatte haben, hilft sicherlich nicht weiter.


onReicht es aus, die Statistiken für die automatische Aktualisierung einzuschalten / beizubehalten , um mögliche statistische Probleme zu ignorieren?
Thomas Stringer

1
Nee. Je größer das System wird, desto mehr Zeilen werden benötigt, damit die automatischen Statistiken aktiviert werden. Die Funktionsweise der automatischen Statistiken besteht darin, dass die Anzahl der Zeilen, die seine 20% der Zeilen in der Tabelle +500 geändert haben (1000 Zeilentabellen erfordern 700) Zu ändernde Zeilen, 1.000.000 Zeilentabellen erfordern 200.500 zu ändernde Zeilen) Der automatische Status wird dann für diese Tabelle (oder den Index oder eine bestimmte Statistik) ausgeführt. Bis dahin bleiben die Statistiken veraltet. Je größer die Tabelle, desto länger dauert es, bis die automatischen Statistiken aktiviert werden. Und nicht diese Zahlen sind nicht einstellbar.
Mrdenny

oh wow, ok, es klingt definitiv so, als ob Sie sich nicht einfach auf die automatische Statistikaktualisierung verlassen können. Nach Ihrer Definition klingt es so, als ob Aktualisierungen der Zeitplanstatistik der richtige Weg sind, insbesondere bei einer Datenbank / Instanz, deren Ausfallzeit, wie ich mir vorstellen kann, geplant wird.
Thomas Stringer

RE: Ihr Kommentar oben zu "nicht einstellbar". Unter SQL Server 2008 R2 ist eine Anpassung über TF 2371
Martin Smith

Sind hier Auto-Statistiken beteiligt? Die Tabellen #tradep und #ttcbm befinden sich nur während der gesamten Laufzeit des Prozesses in tempdb und verweisen nicht auf Tabellen, die keine temporären Tabellen sind.
atommc

5

Zwei Gründe können im Laufe der Zeit zu einer Verbesserung derselben Abfrage führen:

  1. Die Daten ändern sich
  2. Der Abfrageplan ändert sich

Die Daten, gegen die Sie nicht viel tun können. Um zu überprüfen, ob sich der Abfrageplan verbessert, führen Sie die Abfrage manuell aus, wenn Sie wissen, dass die Abfrage am schnellsten ausgeführt wird. SPEICHERN des schnellen Abfrageplans Führen Sie dieselbe Abfrage in einer Zeit aus, in der Sie wissen, dass sie langsam ist. Speichern Sie die langsame Abfrage. Vergleichen Sie die beiden Pläne. Wenn sie unterschiedlich sind, können Sie Ihre Abfrage zwingen, einen gespeicherten Plan zu verwenden. http://technet.microsoft.com/en-us/library/cc917694.aspx


2
Caching kann ebenfalls eine Rolle spielen. Wenn SQL neu gestartet wird, wird der Cache geleert, was möglicherweise erklärt, warum es zunächst so lange dauert. Außerdem muss die Tempdb-Erweiterung erneut durchgeführt werden. Wenn Sie sich auf einer einzelnen Festplatte befinden, verlängert sich dies zunächst ebenfalls.
Datum

Ein Neustart hat keine Auswirkung. Sobald die Abfrage ordnungsgemäß ausgeführt wird, bleibt dies auch so. Die einzige Möglichkeit, die Leistung wieder schlecht zu machen, besteht darin, einen ALTER darauf auszuführen. Der kleinste ALTER-Prozess bewirkt, dass die Abfrage auf die 24-Stunden-Ausführung zurückgesetzt wird.
Atommc

Ich habe Schwierigkeiten herauszufinden, wie ich den guten Plan einer Abfrage erhalten kann, die in einen Prozess eingebettet ist. Wenn ich die Proc-Abfragen extrahiere und in Query Analyzer ausführe, wird der schlechte Plan und die lange Laufzeit wiederhergestellt.
atommc

Holen Sie sich den Abfrageplan für den gesamten Prozess.
Jimbo

4

Es besteht die Möglichkeit, dass die CXPACKET-Wartezeiten tatsächlich überproportional dargestellt werden, wenn viele Threads auf etwas warten, das an E / A gebunden ist. Sie können dies überprüfen, indem Sie MAXDOP=1die Abfrage festlegen und erneut ausführen. Überprüfen Sie, ob der Anteil der Wartezeiten von PAGEIOLATCH-Wartezeiten erheblich zunimmt.

Wenn Ihre PAGEIOLATCH-Wartezeiten einen großen Teil der Wartezeit nach der Überprüfung ausmachen, kann dies darauf hinweisen, dass Ihre Abfrage an E / A gebunden ist.

Ihre Abfrage kann sich selbst korrigieren, da sich der Abfrageplan durch etwas ändert. Das System berücksichtigt bei der Auswahl des geeigneten Abfrageplans den Druck auf Ressourcen wie den Speicher. Der beste Weg, dies zu überprüfen, besteht darin, den Profiler auszuführen und den tatsächlichen Ausführungsplan aus der Abfrage zu erfassen. Wenn Sie die Option haben, legen Sie den Anwendungsnamen für die Verbindung ( Application Name=foobarin der Verbindungszeichenfolge) fest und filtern Sie diesen in der Ablaufverfolgung.

Wenn Sie sehen können, was langsam ist, können Sie möglicherweise die Abfrage optimieren oder eine der Tabellen indizieren.


OK, ich werde eine Spur laufen lassen und sehen, was ich bekomme.
atommc

0

Haben Sie darüber nachgedacht, einen Index für diese temporären Tabellen zu erstellen, nachdem sie erstellt wurden?

Dies könnte ein guter Ausgangspunkt sein. Die Reihenfolge der Felder hängt von der Wertverteilung ab:

CREATE CLUSTERED INDEX IX_tradeP ON #tradeP(cmbId, qs_plyrid, tradeId);

CXPACKETsollte im Moment nicht auf Ihrer Sorgenliste stehen. Meistens ist es der Synchronisierungsthread, der darauf wartet, dass verzerrte Worker-Threads beendet werden. Das Problem beginnt, wenn der Optimierer erwartet, dass die Last gleichmäßig auf die Arbeitsthreads verteilt wird, aber in der tatsächlichen Ausführung ein Thread die gesamte Arbeit erledigt.


0

Total herausgefunden. Ich habe alle gruppierten Primärschlüssel für jede Tabelle entfernt, die an dem Problem beteiligt war. Ich habe die PK durch einen regulären Index ersetzt, der nach dem Einfügen hinzugefügt wurde. Das Problem bestand darin, Hunderte Millionen Zeilen in eine Tabelle mit einem gruppierten Primärschlüssel einzufügen. SQL konnte das aus irgendeinem Grund nicht ertragen. Nachdem ich die Cluster-PK entfernt hatte, dauerte die Einfügung nur wenige Minuten und mein Protokoll wurde nicht um 100 GB vergrößert. Es war nur ein direkter Datenauszug auf den Heap. Das Erstellen des regulären (nicht gruppierten) Index nach dem Einfügen verbesserte die Abfrageleistung, ohne eine Sperrsituation zu erstellen.


Also wird Ihr Tisch jetzt als Haufen aufbewahrt? Sie fügen nach dem Einfügen kein CI zurück?
Martin Smith

Richtig, es ist nur ein Haufen für den Einsatz. Ich füge niemals ein CI hinzu, aber ich füge ihm nach dem Einfügen einen nicht gruppierten Index hinzu.
Atommc

0

Dieses Problem tritt immer wieder auf. Ich denke, es hängt mit der Größe zusammen, die ich für die Datenbank und das Protokoll reserviere. Meine Datenbank ist> 100 GB und ich lasse sie wachsen. Ich denke, was passiert, ist, wenn Autogrow passiert, hängt der Prozess mit dieser Fehlermeldung. Ich werde eine große Größe für Tempdb, Templog und DB / Log zuweisen und prüfen, ob das funktioniert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.