LATCH_EX wartet auf die Ressource METADATA_SEQUENCE_GENERATOR

11

Wir haben einen Prozess, der einen Inventarbericht generiert. Auf der Clientseite teilt der Prozess eine konfigurierbare Anzahl von Arbeitsthreads auf, um einen Datenblock für den Bericht zu erstellen, der einem von vielen Speichern entspricht (möglicherweise Tausende, normalerweise Dutzende). Jeder Arbeitsthread ruft einen Webdienst auf, der eine gespeicherte Prozedur ausführt.

Der Datenbankprozess zum Verarbeiten jedes Blocks sammelt eine Reihe von Daten in einer # Temporären Tabelle. Am Ende jedes Verarbeitungsblocks werden die Daten in eine permanente Tabelle in tempdb geschrieben. Schließlich fordert ein Thread auf der Clientseite am Ende des Prozesses alle Daten aus der permanenten Tempdb-Tabelle an.

Je mehr Benutzer diesen Bericht ausführen, desto langsamer wird er. Ich habe die Aktivität in der Datenbank analysiert. An einem Punkt sah ich 35 separate Anfragen, die alle an einem Punkt des Prozesses blockiert waren. Alle diese SPIDs hatten in der Größenordnung von 50 ms Wartezeiten vom Typ LATCH_EXauf Ressource METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8). Eine SPID verfügt über diese Ressource, und alle anderen blockieren. Ich habe bei einer Websuche nichts über diese Warte-Ressource gefunden.

Die von uns verwendete Tabelle in Tempdb enthält eine IDENTITY(1,1)Spalte. Warten diese SPIDs auf die Spalte IDENTITY? Mit welchen Methoden können wir die Blockierung reduzieren oder beseitigen?

Der Server ist Teil eines Clusters. Auf dem Server wird 64-Bit SQL Server 2012 Standard Edition SP1 unter 64-Bit Windows 2008 R2 Enterprise ausgeführt. Der Server verfügt über 64 GB RAM und 48 Prozessoren, die Datenbank kann jedoch nur 16 verwenden, da es sich um die Standardversion handelt.

(Beachten Sie, dass ich nicht begeistert bin von der Verwendung einer permanenten Tabelle in tempdb, um all diese Daten zu speichern. Eine Änderung wäre eine interessante technische und politische Herausforderung, aber ich bin offen für Vorschläge.)

UPDATE 23.04.2013

Wir haben einen Support-Fall mit Microsoft eröffnet. Ich werde diese Frage auf dem neuesten Stand halten, sobald wir mehr erfahren.

UPDATE 10.05.2013

Der SQL Server-Supporttechniker stimmte zu, dass die Wartezeiten durch die Spalte IDENTITY verursacht wurden. Durch das Entfernen der IDENTITY wurden die Wartezeiten beseitigt. Das Problem konnte in SQL 2008 R2 nicht dupliziert werden. Es trat nur unter SQL 2012 auf.

Paul Williams
quelle
Kopiert der Prozess im Wesentlichen die Daten aus den # Temporären Tabellen in die permanente Tabelle, oder findet in diesem Schritt eine zusätzliche Transformationslogik statt?
Jon Seigel
In dem Schritt, in dem es wartet, werden die Inventardatensätze eines einzelnen Geschäfts ohne Transformation in die permanente Tabelle kopiert. Wir könnten die ganze Zeit in der permanenten Tabelle arbeiten, aber ich denke, der Programmierer hat sich dafür entschieden, eine # Temporäre Tabelle als Haltebereich zu verwenden, um zu verhindern, dass häufige Aktualisierungen der Daten in PAGE-Sperren konvertiert werden.
Paul Williams

Antworten:

4

Angenommen, Sie können das Problem auf die Generierung von Identitätswerten beschränken (versuchen Sie, diese Spalte als Test zu entfernen), würde ich Folgendes empfehlen:

  1. Entfernen Sie die IDENTITYEigenschaft aus der Spalte in der endgültigen Tabelle.
  2. Generieren Sie Identitätswerte in jeder der # Temporären Tabellen.
  3. Kombinieren Sie beim Laden der endgültigen Tabelle eine numerische Kennung für das jeweilige Geschäft mit den Identitätswerten aus Schritt 2.

Wenn Sie also die Speicher-IDs 3 und 4 haben, erhalten Sie die endgültigen ID-Werte wie folgt:

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

Oder so ähnlich. Du hast die Idee.

Dadurch entfällt die Notwendigkeit, bei der IDENTITYGenerierung zu serialisieren, während die Eindeutigkeit des Endergebnisses erhalten bleibt .

Alternativ können Sie je nach Funktionsweise des Prozesses die endgültig berechneten ID-Werte in die # Temporary-Tabellen einfügen. Dann können Sie eine Ansicht erstellen, die UNION ALLsie zusammenfasst, sodass die Daten überhaupt nicht mehr kopiert werden müssen.

Jon Seigel
quelle
Danke für die Antwort. Ich bin damit einverstanden, wenn dies das Problem ist, könnte die Verwendung eines hergestellten Schlüssels (oder gar keinen Schlüssels) das Problem beheben. Wir haben einen Fall mit Microsoft in Bezug auf dieses Problem eröffnet. Ich werde das Ergebnis hier veröffentlichen und Ihre Antwort akzeptieren, wenn sie zustimmen, dass dies das Problem ist.
Paul Williams
@ Paul: Bitte lassen Sie es mich wissen; Ich bin genauso neugierig. Wie Sie konnte ich im Web nichts über diesen Latch finden, aber es ist sicherlich vernünftig, dass es sich um eine Identitäts- / Sequenzserialisierung handelt. Ob dies der Engpass ist oder nicht, ist schwer zu sagen, obwohl es bei mehr als 30 Threads, die um Werte konkurrieren, wahrscheinlich ist. Sie können auch versuchen, von jeder # Temporary-Tabelle in Reihe (anstatt parallel) zu kopieren, um festzustellen, ob dies hilfreich ist.
Jon Seigel
2
Der SQL Server-Techniker stimmte zu, dass es sich wahrscheinlich um die IDENTITYSpalte handelte. Wir haben es aus dem bereits breiten Clustered-Index entfernt und die Spalte vollständig entfernt. Es war nicht nötig. Danach verschwanden diese LATCH_EX-Wartezeiten. Wir konnten die Wartezeiten in SQL 2008 R2 nicht duplizieren. Das Problem trat nur auf SQL Server 2012 auf.
Paul Williams
@ Paul: Danke für das Follow-up. Sehr interessant. Ich vermute, dass der Code, der IDENTITYWerte generiert , neu geschrieben wurde, um das neue Sequenzgenerierungsmaterial zu verwenden, das 2012 neu war. Auf <2012 wird möglicherweise ein anderer Latch-Typ angezeigt. Wenn jedoch kein Perf-Problem aufgetreten ist, scheint dies der Fall zu sein eine Regression im Code. In jedem Fall ist das Entfernen der IDENTITYSäule am sichersten.
Jon Seigel
Anstelle der Identität könnten Sie versuchen, eine 'SEQUENCE' (neu in SQL 2012) zu verwenden
Bogdan Maxim
7

(Aktualisiert Februar 2019)

Dies ist ein alter Beitrag, der besagt, dass ich es endlich geschafft habe, Microsoft davon zu überzeugen, dass die Tatsache, dass dies geschieht, tatsächlich ein Defekt ist.

Update: MS hat den Fehler bestätigt und ihm die Fehlernummer 12628722 zugewiesen.

Ich hatte diesen Beitrag im vergangenen November 2018 gesehen, als wir nach dem Upgrade von SQL Server 2005 auf SQL Server 2017 zu leiden hatten. Eine 3,3-Millionen-Zeilentabelle, die 10 Sekunden für das Masseneinfügen benötigte, dauerte plötzlich 10 Sekunden Minuten auf Tabellen mit IdentitySpalten.

Es stellt sich heraus, dass dahinter zwei Probleme stehen:

  1. Microsoft hat das Verhalten in SQL Server 2014 geändert, um die parallele Ausführung von Bulk-Inserts zu erzwingen. In früheren Versionen wurde Bulk-Inserts ein serialisierter Plan zugewiesen.
  2. Sobald der Motor auf unserer 32-Kern-Box parallel lief, verbrachte er mehr Zeit damit, dass sich die Kerne gegenseitig verriegelten, als die eigentliche Arbeit zu erledigen.

Ich habe 4 Wochen gebraucht, aber kurz nach den Ferien bekam ich ein verspätetes Geschenk vom Weihnachtsmann - eine Bestätigung, dass das Problem tatsächlich ein Defekt war.

Es gibt einige mögliche Problemumgehungen, die wir gefunden haben, bis dies behoben ist:

  1. Verwenden Sie Option (MaxDop 1)in der Abfrage, um die Masseneinfügung wieder in einen serialisierten Plan umzuwandeln.
  2. Maske die Identitätsspalte durch Gießen (z Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn)
    • Dies verhindert, dass die Identitätseigenschaft bei Verwendung kopiert wird SELECT...INTO
  3. Entfernen Sie die Identitätsspalte wie oben beschrieben.
  4. Ändern Sie den Datenbankkompatibilitätsmodus auf SQL Server 2012 oder niedriger, um einen serialisierten Plan wiederherzustellen.

Update: Der Fix, den MS implementieren wird, besteht darin, diese Art von Inserts wieder auf die Verwendung eines Serialized Plans zurückzuführen. Dies ist für SQL Server 2017 CU14 geplant (keine Neuigkeiten zu anderen Versionen von SQL Server - sorry!). Bei der Implementierung muss das Trace-Flag 9492 entweder auf Serverebene oder über aktiviert werden DBCC TraceOn .

Rachel Ambler
quelle