Database
 sql >> Datenbank >  >> RDS >> Database

Knie-Ruck-Wartestatistik:CXPACKET

In mehreren meiner Posts im letzten Jahr habe ich das Thema verwendet, dass Leute einen bestimmten Wartetyp sehen und dann „reflexartig“ auf das Warten reagieren. Typischerweise bedeutet dies, dass Sie einigen schlechten Internetratschlägen folgen und drastische, unangemessene Maßnahmen ergreifen oder vorschnell zu einer Schlussfolgerung über die eigentliche Ursache des Problems kommen und dann Zeit und Mühe mit einer wilden Verfolgungsjagd verschwenden.

Einer der Wartetypen, bei denen reflexartige Reaktionen am stärksten sind und bei denen einige der schlechtesten Ratschläge existieren, ist das CXPACKET-Warten. Es ist auch der Wartetyp, der am häufigsten auf den Servern der Leute wartet (laut meinen beiden großen Umfragen zu Wartetypen aus den Jahren 2010 und 2014 – siehe hier für Details), also werde ich ihn in diesem Beitrag behandeln.

Was bedeutet der CXPACKET-Wartetyp?

Die einfachste Erklärung ist, dass CXPACKET bedeutet, dass Abfragen parallel ausgeführt werden und Sie *immer* sehen, dass CXPACKET auf eine parallele Abfrage wartet. CXPACKET-Wartezeiten bedeuten NICHT, dass Sie problematische Parallelität haben – Sie müssen tiefer graben, um das festzustellen.

Betrachten Sie als Beispiel für einen parallelen Operator den Repartition Streams-Operator, der in grafischen Abfrageplänen über das folgende Symbol verfügt:

Und hier ist ein Bild, das zeigt, was in Bezug auf parallele Threads für diesen Operator vor sich geht, mit einem Parallelitätsgrad (DOP) von 4:

Für DOP =4 gibt es vier Producer-Threads, die Daten von früher im Abfrageplan ziehen, die Daten gehen dann über vier Consumer-Threads zurück an den Rest des Abfrageplans.

Sie können die verschiedenen Threads in einem parallelen Operator sehen, die auf eine Ressource warten, indem Sie sys.dm_os_waiting_tasks verwenden DMV, in der exec_context_id Spalte (dieser Beitrag hat mein Skript dafür).

Es gibt immer einen „Kontroll“-Thread für jeden parallelen Plan, der aus historischen Gründen immer die Thread-ID 0 hat. Der Kontroll-Thread registriert immer eine CXPACKET-Wartezeit, wobei die Dauer gleich der Zeitdauer ist, die der Plan für die Ausführung benötigt. Paul White hat hier eine großartige Erklärung für Threads in parallelen Plänen.

CXPACKET-Wartevorgänge werden von Nicht-Steuerungs-Threads nur dann registriert, wenn sie vor den anderen Threads im Operator abgeschlossen werden. Dies kann passieren, wenn einer der Threads lange Zeit beim Warten auf eine Ressource hängen bleibt. Sehen Sie also nach, was der Wartetyp des Threads ist, der CXPACKET nicht anzeigt (mit meinem obigen Skript), und beheben Sie den Fehler entsprechend. Dies kann auch aufgrund einer verzerrten Arbeitsverteilung zwischen den Threads passieren, und ich werde in meinem nächsten Beitrag hier näher auf diesen Fall eingehen (er wird durch veraltete Statistiken und andere Probleme bei der Kardinalitätsschätzung verursacht).

Beachten Sie, dass Consumer-Threads in SQL Server 2016 SP2 und SQL Server 2017 RTM CU3 keine CXPACKET-Wartevorgänge mehr registrieren. Sie registrieren CXCONSUMER Waits, die harmlos sind und ignoriert werden können. Dadurch soll die Anzahl der generierten CXPACKET-Wartevorgänge reduziert werden, und die verbleibenden sind mit größerer Wahrscheinlichkeit umsetzbar.

Unerwartete Parallelität?

Da CXPACKET einfach bedeutet, dass Parallelität stattfindet, sollten Sie sich zunächst ansehen, ob Sie Parallelität für die Abfrage erwarten, die sie verwendet. Meine Abfrage gibt Ihnen die Knoten-ID des Abfrageplans, wo die Parallelität stattfindet (sie zieht die Knoten-ID aus dem XML-Abfrageplan heraus, wenn der Wartetyp des Threads CXPACKET ist). Suchen Sie also nach dieser Knoten-ID und bestimmen Sie, ob die Parallelität sinnvoll ist .

Einer der häufigsten Fälle von unerwarteter Parallelität ist, wenn ein Tabellenscan stattfindet, bei dem Sie eine kleinere Indexsuche oder einen kleineren Scan erwarten. Sie sehen dies entweder im Abfrageplan oder Sie sehen viele PAGEIOLATCH_SH-Wartevorgänge (hier ausführlich besprochen) zusammen mit den CXPACKET-Wartevorgängen (ein klassisches Wartestatistikmuster, auf das Sie achten sollten). Es gibt eine Vielzahl von Ursachen für unerwartete Tabellenscans, darunter:

  • Fehlender Nonclustered-Index, daher ist ein Tabellenscan die einzige Alternative
  • Veraltete Statistiken, sodass der Abfrageoptimierer denkt, dass ein Tabellenscan die beste Datenzugriffsmethode ist
  • Eine implizite Konvertierung aufgrund eines Datentypkonflikts zwischen einer Tabellenspalte und einer Variablen oder einem Parameter, was bedeutet, dass ein nicht gruppierter Index nicht verwendet werden kann
  • Arithmetik wird für eine Tabellenspalte statt für eine Variable oder einen Parameter ausgeführt, was bedeutet, dass ein Nonclustered-Index nicht verwendet werden kann

In all diesen Fällen hängt die Lösung davon ab, was Ihrer Meinung nach die eigentliche Ursache ist.

Aber was ist, wenn es keinen offensichtlichen Grundfall gibt und die Abfrage nur als teuer genug angesehen wird, um einen parallelen Plan zu rechtfertigen?

Verhindern von Parallelität

Unter anderem entscheidet der Abfrageoptimierer, einen parallelen Abfrageplan zu erstellen, wenn der serielle Plan höhere Kosten hat als der cost threshold for parallelism , eine sp_configure-Einstellung für die Instanz. Der Kostenschwellenwert für Parallelität (oder CTFP) ist standardmäßig auf fünf festgelegt, was bedeutet, dass ein Plan nicht sehr teuer sein muss, um die Erstellung eines parallelen Plans auszulösen.

Eine der einfachsten Möglichkeiten, unerwünschte Parallelität zu verhindern, besteht darin, den CTFP auf eine viel höhere Zahl zu erhöhen. Je höher Sie ihn einstellen, desto weniger wahrscheinlich werden parallele Pläne erstellt. Einige Leute befürworten eine Einstellung von CTFP auf irgendwo zwischen 25 und 50, aber wie bei allen anpassbaren Einstellungen ist es am besten, verschiedene Werte zu testen und zu sehen, was für Ihre Umgebung am besten funktioniert. Wenn Sie eine etwas programmatischere Methode zur Auswahl eines guten CTFP-Werts wünschen, hat Jonathan einen Blogbeitrag geschrieben, der eine Abfrage zeigt, um den Plan-Cache zu analysieren und einen vorgeschlagenen Wert für CTFP zu erzeugen. Als Beispiel haben wir einen Client mit CTFP auf 200 und einen anderen auf das Maximum – 32767 – eingestellt, um jegliche Parallelität zwangsweise zu verhindern.

Sie fragen sich vielleicht, warum der zweite Client CTFP als Vorschlaghammermethode zum Verhindern von Parallelität verwenden musste, wenn Sie meinen, er könnte einfach den „maximalen Grad an Parallelität“ (oder MAXDOP) des Servers auf 1 setzen. Nun, jeder mit jeder Berechtigungsstufe kann das Geben Sie einen Abfrage-MAXDOP-Hinweis an und überschreiben Sie die Server-MAXDOP-Einstellung, aber CTFP kann nicht überschrieben werden.

Und das ist eine weitere Methode zur Begrenzung der Parallelität – das Setzen eines MAXDOP-Hinweises auf die Abfrage, die nicht parallel gehen soll.

Sie könnten auch die MAXDOP-Einstellung des Servers verringern, aber das ist eine drastische Lösung, da es alles daran hindern kann, Parallelität zu verwenden. Es ist heutzutage üblich, dass Server gemischte Workloads haben, beispielsweise mit einigen OLTP-Abfragen und einigen Berichtsabfragen. Wenn Sie den Server-MAXDOP senken, werden Sie die Leistung der Berichtsabfragen beeinträchtigen.

Eine bessere Lösung bei einer gemischten Arbeitslast wäre die Verwendung von CTFP, wie oben beschrieben, oder die Verwendung von Resource Governor (was leider nur für Unternehmen gilt). Sie können die Ressourcenkontrolle verwenden, um die Workloads in Workload-Gruppen aufzuteilen, und dann für jede Workload-Gruppe einen MAX_DOP (der Unterstrich ist kein Tippfehler) festlegen. Und das Gute an der Verwendung von Resource Governor ist, dass MAX_DOP nicht durch einen MAXDOP-Abfragehinweis überschrieben werden kann.

Zusammenfassung

Fallen Sie nicht in die Falle zu denken, dass CXPACKET automatisch wartet, was bedeutet, dass Sie eine schlechte Parallelität haben, und befolgen Sie auf keinen Fall einige der Internet-Ratschläge, die ich gesehen habe, um den Server zuzuschlagen, indem Sie MAXDOP auf 1 setzen. Nehmen Sie sich die Zeit um zu untersuchen, warum Sie CXPACKET-Wartezeiten sehen und ob es sich um etwas handelt, das behoben werden muss, oder nur um ein Artefakt einer Workload, die ordnungsgemäß ausgeführt wird.

In Bezug auf allgemeine Wartestatistiken finden Sie weitere Informationen zu deren Verwendung für die Fehlerbehebung in:

  • Meine SQLskills-Blogbeitragsserie, beginnend mit Wait-Statistiken, oder sagen Sie mir bitte, wo es wehtut
  • Meine Wait Types und Latch Classes Bibliothek hier
  • Mein Pluralsight-Online-Schulungskurs SQL Server:Fehlerbehebung bei der Leistung mithilfe von Wartestatistiken
  • SQL Sentry Performance Advisor

Im nächsten Artikel der Serie werde ich die schiefe Parallelität besprechen und Ihnen eine einfache Möglichkeit geben, dies zu sehen. Bis dahin viel Spaß bei der Fehlersuche!