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

Knie-Ruck-Wartestatistik:PAGEATCH

In den letzten 18 Monaten habe ich mich auf spontane Reaktionen auf die Analyse von Wartestatistiken und andere Themen im Zusammenhang mit der Leistungsoptimierung konzentriert, und in diesem Beitrag werde ich damit fortfahren und den PAGELATCH_XX besprechen wartet. Das XX am Ende der Wartezeit bedeutet, dass es mehrere Arten von PAGELATCH gibt Warten Sie, und die häufigsten Beispiele sind:

  • PAGELATCH_SH – ( SH sind) warten auf den Zugriff auf eine Datendateiseite im Speicher, damit die Seiteninhalte gelesen werden können
  • PAGELATCH_EX oder PAGELATCH_UP – (Bsp. inclusive oder UP Datum) Warten auf Zugriff auf eine Datendateiseite im Speicher, damit der Seiteninhalt geändert werden kann

Wenn einer dieser Wartetypen auf einem Server am weitesten verbreitet ist, ist die spontane Reaktion, dass das Problem etwas mit I/O zu tun hat (d. h. Verwechslung mit dem PAGEIOLATCH_XX Wartetyp, den ich 2014 in einem Beitrag behandelt habe) und jemand versucht, mehr Speicher hinzuzufügen oder das I/O-Subsystem zu optimieren. Keine dieser Reaktionen hat überhaupt einen Effekt, da die umkämpften Datendateiseiten bereits im Pufferpool gespeichert sind!

In allen Fällen können Sie sehen, ob Sie ein Problem mit PAGELATCH_XX haben Konflikte mithilfe von sys.dm_os_waiting_tasks Skript in meinem Blog oder mit einem Tool wie Performance Advisor, wie in diesem Beitrag (für einen anderen Wartetyp) gezeigt.

Was ist also die Quelle des Streits? Zuerst werde ich den Hintergrund hinter diesen Wartetypen erläutern und dann auf die beiden häufigsten Ursachen für PAGELATCH_XX eingehen Streit.

Hintergrund:Sperren

Bevor ich auf einige der Ursachen von PAGELATCH_XX eingehe wartet, ich möchte erklären, warum es sie überhaupt gibt.

In jedem Multithread-System müssen Datenstrukturen, auf die von mehreren Threads zugegriffen und diese bearbeitet werden können, geschützt werden, um Szenarien wie die folgenden zu verhindern:

  • Zwei Threads aktualisieren gleichzeitig eine Datenstruktur, und einige der Aktualisierungen gehen verloren
  • Ein Thread aktualisiert eine Datenstruktur gleichzeitig mit einem anderen Thread, der die Datenstruktur liest, sodass der lesende Thread eine Mischung aus alten und neuen Daten sieht

Dies ist grundlegende Informatik, und SQL Server ist nicht anders, daher müssen alle Datenstrukturen innerhalb von SQL Server über eine Multithread-Zugriffssteuerung verfügen.

Einer der Mechanismen, die SQL Server dazu verwendet, wird als Latch bezeichnet, wobei das Halten des Latch im exklusiven Modus verhindert, dass andere Threads auf die Datenstruktur zugreifen, und das Halten des Latch im Share-Modus verhindert, dass andere Threads die Datenstruktur ändern. SQL Server verwendet auch Spinlocks für einige Datenstrukturen und ich habe diese bereits 2014 in diesem Beitrag besprochen.

Aber warum ist eine Datendateiseite im Speicher durch einen Latch geschützt, fragen Sie sich vielleicht? Nun, eine Datendateiseite ist nur eine Datenstruktur, wenn auch für einen speziellen Zweck, und benötigt daher die gleichen Zugriffskontrollen wie jede andere Datenstruktur. Wenn also ein Thread eine Datendateiseite ändern muss, muss er einen Exklusiv- oder Update-Latch auf der Seite erwerben, und wenn er nicht warten kann und muss, geben Sie den Wartetyp PAGELATCH_EX ein oder PAGELATCH_UP Ergebnisse.

Klassischer tempdb-Konflikt

PAGELATCH Konflikte in tempdb treten typischerweise bei Zuordnungs-Bitmaps auf und treten bei Workloads mit vielen gleichzeitigen Verbindungen auf, die kleine temporäre Tabellen (die in tempdb gespeichert sind) erstellen und löschen.

Wenn die erste Zeile in eine temporäre Tabelle eingefügt wird, müssen zwei Seiten zugewiesen werden (eine Datenseite und eine IAM-Seite, die die Datenseite verfolgt). Diese Seiten müssen auf einer speziellen Zuordnungsseite namens PFS-Seite als zugeordnet markiert werden und werden standardmäßig von speziellen Datenbereichen zugeordnet, die von einer anderen Zuordnungsseite namens SGAM-Seite verfolgt werden (Einzelheiten dazu finden Sie in meinem alten Blogbeitrag hier). Wenn die temporäre Tabelle gelöscht wird, müssen diese Seiten wieder freigegeben werden, was weitere Änderungen an den PFS- und SGAM-Seiten erforderlich macht.

Wenn die temporären Tabellen klein sind und die kumulierte Größe aller gleichzeitig erstellten temporären Tabellen weniger als 64 MB beträgt, werden alle diese Zuordnungs-Bitmap-Änderungen auf den allerersten PFS- und SGAM-Seiten in der tempdb-Datendatei zentriert (mit der Seiten-ID (1:1) bzw. (1:3)). Das Aktualisieren einer dieser Zuordnungsseiten erfordert das Zwischenspeichern der Seite, und es kann jeweils nur ein Thread die Seite ändern, sodass alle anderen Threads warten müssen – mit Wartetyp PAGELATCH_UP .

Ab SQL Server 2005 können temporäre Tabellen beim Löschen zwischengespeichert werden, solange sie weniger als 8 MB groß sind (und in SQL Server 2014 nicht in einer gespeicherten Prozedur erstellt werden, die auch DDL-Anweisungen für die temporäre Tabelle enthält). Das bedeutet, dass der nächste Thread, der denselben Abfrageplan ausführt, die temporäre Tabelle aus dem Cache nehmen kann und sich nicht mit den anfänglichen Zuordnungen befassen muss. Dadurch werden Konflikte bei den Zuweisungs-Bitmaps reduziert, aber der Cache für temporäre Tabellen ist nicht sehr groß, sodass bei Workloads mit Hunderten von gleichzeitigen Erstellungen/Löschungen temporärer Tabellen immer noch viele Konflikte auftreten.

Es ist trivial, den Konflikt auf den SGAM-Seiten in tempdb zu verhindern, indem das dokumentierte Trace-Flag 1118 auf dem Server aktiviert wird, das meiner Meinung nach auf allen Servern auf der ganzen Welt aktiviert sein sollte und tatsächlich das unveränderliche Standardverhalten in SQL Server 2016 ist>

Das Verhindern von Konflikten auf den PFS-Seiten in tempdb ist etwas schwieriger. Unter der Annahme, dass die temporären Tabellen für die Leistung benötigt werden, besteht der Trick darin, mehrere Datendateien für tempdb zu haben, damit die Zuordnungen Round-Robin zwischen den Dateien erfolgen, der Konflikt auf mehrere PFS-Seiten aufgeteilt wird und der Gesamtkonflikt abnimmt. Leider gibt es keine richtige Antwort darauf, wie viele Dateien Sie haben sollten. Weitere Informationen zu den allgemein akzeptierten Leitlinien hierzu finden Sie im KB-Artikel 2154845 und in diesem Blogbeitrag.

Hotspot einfügen

In Benutzerdatenbanken eine häufige Ursache für eine hohe Anzahl von PAGELATCH_EX Waits ist ein Insert-Hotspot.

Dies kann auftreten, wenn eine Tabelle einen gruppierten Index mit einem Clusterschlüssel int oder bigint und eine Zeilengröße hat, die klein genug ist, sodass viele zehn oder mehr Tabellenzeilen auf einer Datenseite auf der Blattebene des gruppierten Indexes Platz finden.

Wenn die Arbeitslast für eine solche Tabelle viele Dutzende oder Hunderte gleichzeitiger Threads umfasst, die in die Tabelle einfügen, generieren viele der Threads Zeilen mit Identitätswerten (und damit Clusterschlüsseln), die auf derselben Datenseite auf Blattebene eingefügt werden müssen .

Denken Sie jetzt daran, dass jede Änderung an einer Datendateiseite im Speicher einen exklusiven Latch erfordert, sodass jeder der Threads, die versuchen, auf derselben Seite einzufügen, exklusiv den Latch der Seite erwerben muss. Während jeder Thread den exklusiven Latch hält, warten die anderen Threads auf PAGELATCH_EX für diese Seite, wodurch die gleichzeitigen Einfügungen im Wesentlichen zu einem stark eingeschränkten synchronen Prozess werden.

Es gibt einige mögliche Lösungen für dieses Problem:

  • Verwenden Sie einen zufälligeren Schlüssel und erkennen Sie, dass dies zu einer Indexfragmentierung führt. Verwenden Sie daher auch einen Indexfüllfaktor, um Seitenteilungen zu verhindern
  • Verteilen Sie die Einfügungen mithilfe eines künstlichen Partitionierungsmechanismus in der Tabelle
  • Verwenden Sie eine längere Tabellenzeilengröße (dies ist offensichtlich die am wenigsten schmackhafte Option)

Ich habe gesehen, dass ein Insert-Hotspot wie dieser auftaucht, wenn jemand versucht hat, Indexfragmentierungsprobleme zu beseitigen, indem er einen zufälligen GUID-Cluster-Schlüssel in einen int- oder bigint-Identitäts-Cluster-Schlüssel geändert hat, aber das neue Tabellenschema unter Produktionslasten nicht getestet hat.

Zusammenfassung

Genau wie bei anderen Wartetypen, genau verstehen, was PAGELATCH_XX ist Waits bedeuten, ist der Schlüssel zum Verständnis, wie sie behoben werden können.

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

Bis zum nächsten Mal, viel Spaß bei der Fehlersuche!