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

Knie-Ruck-Wartestatistik:SOS_SCHEDULER_YIELD

In meinem vorherigen Beitrag habe ich LCK_M_XX-, ASYNC_NETWORK_IO- und OLEDB-Wartezeiten und die spontanen Reaktionen darauf besprochen. In diesem Beitrag werde ich mit dem Thema Wartestatistik fortfahren und die Wartezeit von SOS_SCHEDULER_YIELD besprechen.

Wenn SOS_SCHEDULER_YIELD auf einem Server am weitesten verbreitet ist, ist es üblich, eine anhaltend hohe CPU-Auslastung zu sehen. Die reflexartige Reaktion hier ist, dass der Server unter CPU-Last stehen muss oder dass ein Spinlock das Problem ist.

Wir brauchen hier ein wenig Hintergrundwissen, um diese beiden Reaktionen zu verstehen.

Thread-Planung

Die Threadplanung in SQL Server wird von SQL Server selbst verwaltet, nicht von Windows (d. h. es ist nicht präemptiv). Der SQL OS-Teil der Speicher-Engine bietet Scheduling-Funktionalität und Threads wechseln von der Ausführung auf einem Prozessor (wobei der Thread-Status RUNNING ist) zu einem Status auf der Warteliste, der darauf wartet, dass eine Ressource verfügbar wird (Status SUSPENDED), zu einem Status auf Runnable Warteschlange, sobald die Ressource verfügbar wird (Zustand RUNNABLE) und darauf wartet, an den Anfang der Warteschlange zu gelangen und wieder zurück auf den Prozessor (zurück zum Zustand RUNNING). Ich habe Processor, Waiter List und Runnable Queue groß geschrieben, um sie als Teile eines Planers zu identifizieren.

Immer wenn ein Thread eine Ressource benötigt, die er nicht sofort erwerben kann, wird er ausgesetzt und wartet auf die Warteliste, um mitgeteilt (signalisiert) zu werden, dass seine Ressource verfügbar ist. Die auf der Warteliste verbrachte Zeit ist die Ressourcenwartezeit und die auf der Runnable Queue verbrachte Zeit ist die Signalwartezeit. Zusammen ergeben sie die Gesamtwartezeit. Das SQL-Betriebssystem verfolgt die Wartezeit und die Signalwartezeit, daher müssen wir die Ausgabe von sys.dm_os_wait_stats rechnen, um die Ressourcenwartezeit abzuleiten (siehe mein Skript hier).

Die Warteliste ist ungeordnet (jeder Thread darauf kann jederzeit signalisiert und in die Runnable Queue verschoben werden) und die Runnable Queue ist fast 100 % der Zeit First-In-First-Out (FIFO). Die einzige Ausnahme von der Runnable Queue, die FIFO ist, ist, wenn mehrere Resource Governor-Workload-Gruppen im selben Ressourcenpool konfiguriert wurden und sie relativ zueinander unterschiedliche Prioritäten haben. Ich habe noch nie gesehen, dass dies erfolgreich in der Produktion eingesetzt wurde, daher werde ich nicht weiter darauf eingehen.

Es gibt noch einen weiteren Grund, warum ein Thread den Prozessor verlassen muss – er erschöpft sein Quantum. Das Thread-Quantum in SQL OS ist auf 4 Millisekunden festgelegt. Der Thread selbst ist dafür verantwortlich, festzustellen, ob sein Quantum erschöpft ist (durch Aufrufen von Hilfsroutinen im SQL-Betriebssystem) und den Prozessor freiwillig aufzugeben (bekannt als Yielding). Wenn dies auftritt, bewegt sich der Thread direkt an das Ende der Runnable Queue, da es nichts gibt, auf das er warten könnte. Das SQL-Betriebssystem muss jedoch für diesen Übergang vom Prozessor einen Wartetyp registrieren und registriert SOS_SCHEDULER_YIELD.

Dieses Verhalten wird oft mit CPU-Druck verwechselt, ist es aber nicht – es ist nur eine anhaltende CPU-Auslastung. CPU-Auslastung und deren Erkennung ist ein ganz anderes Thema für einen zukünftigen Beitrag. Soweit es diesen Beitrag betrifft, ist es ziemlich sicher, dass CPU-Last kein Problem ist, solange die durchschnittliche Signalwartezeit niedrig ist (0-0,1-0,2 ms).

Spinlocks

Ein Spinlock ist ein Synchronisierungselement auf sehr niedriger Ebene, das verwendet wird, um Thread-sicheren Zugriff auf Datenstrukturen in SQL Server bereitzustellen, die extrem heiß sind (sehr volatil und unglaublich häufig von mehreren Threads aufgerufen und geändert). Beispiele für solche Strukturen sind die pufferfreie Liste in jedem Teil des Pufferpools und das Gewichtungsarray für die proportionale Füllung für die Datendateien in einer Dateigruppe.

Wenn ein Thread einen Spinlock erwerben muss, prüft er, ob der Spinlock frei ist, und erwirbt ihn, wenn ja, sofort (unter Verwendung eines verriegelten Assembler-Primitives wie „Testbit löschen und setzen“). Wenn der Spinlock nicht erworben werden kann, versucht der Thread sofort, ihn erneut zu erwerben, und immer wieder, und zwar für bis zu tausend Iterationen, bis er sich zurückzieht (ein wenig schläft). Dies wird nicht als Wartetyp registriert, da der Thread einfach die Windows-Funktion sleep () aufruft, aber andere Threads, die warten, große (10-20 ms+) Signalwartezeiten haben können, da der schlafende Thread bis dahin auf dem Prozessor bleibt erhält das Spinlock.

Warum spreche ich über Spinlocks? Weil sie auch eine Ursache für eine hohe CPU-Auslastung sein können und es ein Missverständnis gibt, dass Spinlocks eine Ursache für SOS_SCHEDULER_YIELD-Wartezeiten sind. Sie sind es nicht.

SOS_SCHEDULER_YIELD Ursachen

Es gibt also eine Ursache für SOS_SCHEDULER_YIELD:Ein Thread, der sein Scheduling-Quantum erschöpft, und stark wiederkehrende Instanzen können dazu führen, dass SOS_SCHEDULER_YIELD zusammen mit einer hohen CPU-Auslastung die häufigste Wartezeit ist.

SOS_SCHEDULER_YIELD Waits werden in der Ausgabe von sys.dm_os_waiting_tasks nicht angezeigt, da der Thread nicht wartet. Sie können sehen, welche Abfrage die SOS_SCHEDULER_YIELD-Wartezeiten generiert, indem Sie sys.dm_exec_requests abfragen und nach der Spalte last_wait_type filtern.

Das bedeutet auch, dass, wenn Sie SOS_SCHEDULER_YIELD in der Ausgabe von sys.dm_os_wait_stats sehen, die Ressourcenwartezeit Null ist, weil sie nicht wirklich gewartet hat. Denken Sie jedoch daran, dass jedes dieser "Wartezeiten" 4 ms CPU-Zeit entspricht, die für die Abfrage aufgelaufen ist.

Die einzige Möglichkeit, um nachzuweisen, was SOS_SCHEDULER_YIELD-Wartevorgänge verursacht, besteht darin, SQL Server-Aufruflisten zu erfassen, wenn dieser Wartetyp auftritt, indem erweiterte Ereignisse und Debugsymbole von Microsoft verwendet werden. Ich habe einen Blogbeitrag, der beschreibt und zeigt, wie diese Untersuchung durchgeführt wird, und es gibt ein großartiges Whitepaper über Spinlocks und Spinlock-Untersuchungen, das es wert ist, gelesen zu werden, wenn Sie an dieser Tiefe der Interna interessiert sind.

Für den Fall der Quantenerschöpfung ist das nicht die eigentliche Ursache. Es ist ein weiteres Symptom. Jetzt müssen wir überlegen, warum ein Thread sein Quantum wiederholt erschöpft.

Ein Thread kann sein Quantum nur erschöpfen, wenn er 4 ms lang mit der Verarbeitung von SQL Server-Code fortfahren kann, ohne eine Ressource zu benötigen, die ein anderer Thread besitzt – kein Warten auf Sperren, Seitenlatches, Datendateiseiten, die von der Festplatte gelesen werden müssen, Speicherzuweisungen, Dateiwachstum, Protokollierung , oder die unzähligen anderen Ressourcen, die ein Thread möglicherweise benötigt.

Der häufigste Codeabschnitt, bei dem eine Quantenerschöpfung auftreten und große Mengen an SOS_SCHEDULER_YIELD-Wartezeiten verursachen kann, ist das Scannen eines Index/einer Tabelle, in der sich alle erforderlichen Datendateiseiten im Speicher befinden und es keine Konkurrenz für den Zugriff auf diese Seiten gibt, und das ist es also Ich empfehle Ihnen, in Abfrageplänen nachzusehen, wenn Sie SOS_SCHEDULER_YIELD als den wichtigsten Wartetyp sehen – große und/oder wiederholte Index-/Tabellenscans.

Das bedeutet nicht, dass große Scans schlecht sind, da es sein könnte, dass der effizienteste Weg zur Verarbeitung Ihrer Arbeitslast ein Scan ist. Wenn die SOS_SCHEDULER_YIELD-Wartezeiten jedoch neu und ungewöhnlich sind und durch große Scans verursacht werden, sollten Sie untersuchen, warum die Abfragepläne Scans verwenden. Vielleicht hat jemand einen kritischen Nonclustered-Index gelöscht, oder die Statistiken sind veraltet, sodass ein falscher Abfrageplan ausgewählt wurde, oder vielleicht wurde ein ungewöhnlicher Parameterwert an eine gespeicherte Prozedur übergeben, und der Abfrageplan erforderte einen Scan oder eine Codeänderung trat ohne unterstützende Indexergänzungen auf.

Zusammenfassung

Genau wie bei anderen Wartetypen ist es wichtig, genau zu verstehen, was SOS_SCHEDULER_YIELD bedeutet, um zu verstehen, wie es behoben werden kann und ob das Verhalten aufgrund der verarbeiteten Arbeitslast erwartet wird.

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

  • My SQLskills-Blogbeitragsserie, beginnend mit Wait-Statistiken, oder sagen Sie mir bitte, wo es wehtut
  • Meine Wartetypen- und Latch-Klassen-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 einen anderen Wartetyp besprechen, der eine häufige Ursache für reflexartige Reaktionen ist. Bis dahin viel Spaß bei der Fehlersuche!