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.
dual cpu 32 bit W2K8
Zeit für ein Upgrade auf 64Bit. Haben Sie auch / 3GB Switch zusammen mit AWE aktiviert?Antworten:
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.
quelle
on
Reicht es aus, die Statistiken für die automatische Aktualisierung einzuschalten / beizubehalten , um mögliche statistische Probleme zu ignorieren?Zwei Gründe können im Laufe der Zeit zu einer Verbesserung derselben Abfrage führen:
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
quelle
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=1
die 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=foobar
in 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.
quelle
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:
CXPACKET
sollte 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.quelle
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.
quelle
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.
quelle