Frage

Ich habe einen sehr großen Datensatz (ca. 3 Millionen Datensätze), der täglich mit Aktualisierungen und neuen Datensätzen zusammengeführt werden muss.Ich habe eine gespeicherte Prozedur, die den Datensatz tatsächlich in 1000 Datensatzblöcke aufteilt und verwendet MERGE Befehl mit temporären Tabellen, um zu vermeiden, dass die Live-Tabelle gesperrt wird, während die Daten aktualisiert werden.Das Problem ist, dass es nicht wirklich hilft.Die Tabelle „blockiert“ immer noch und unsere Website, die die Daten verwendet, erhält Zeitüberschreitungen, wenn versucht wird, auf die Daten zuzugreifen.Ich habe sogar versucht, es in 100 Plattenblöcke aufzuteilen, und sogar einen WAITFOR DELAY '000:00:5' um zu sehen, ob es hilfreich wäre, zwischen dem Zusammenführen der Blöcke eine Pause einzulegen.Es ist immer noch ziemlich träge.

Ich suche nach Vorschlägen, Best Practices oder Beispielen zum Zusammenführen großer Datenmengen, ohne die Tabellen zu sperren.

Danke

War es hilfreich?

Lösung

Ändern Sie Ihr Frontend so, dass es dabei NOLOCK oder READ UNCOMMITTED verwendet wählt.

Sie können MERGE, INSERT oder UPDATE nicht mit NOLOCK sperren, da die Datensätze gesperrt sein müssen, um die Aktualisierung durchzuführen.Sie können die SELECTS jedoch mit NOLOCK sperren.

Beachten Sie, dass Sie dies mit Vorsicht verwenden sollten.Wenn Dirty Reads in Ordnung sind, fahren Sie fort.Wenn die Lesevorgänge jedoch die aktualisierten Daten erfordern, müssen Sie einen anderen Weg einschlagen und genau herausfinden, warum das Zusammenführen von 3M-Datensätzen ein Problem verursacht.

Ich wette, dass die meiste Zeit damit verbracht wird, während des Zusammenführungsbefehls Daten von der Festplatte zu lesen und/oder Situationen mit wenig Arbeitsspeicher zu umgehen.Möglicherweise ist es besser, einfach mehr RAM in Ihren Datenbankserver zu stopfen.

Ideal wäre es, über genügend RAM zu verfügen, um bei Bedarf die gesamte Datenbank in den Speicher zu laden.Wenn Sie beispielsweise über eine 4-GB-Datenbank verfügen, stellen Sie sicher, dass Sie über 8 GB RAM verfügen.natürlich auf einem x64-Server.

Andere Tipps

Ich fürchte, dass ich genau das Gegenteil erlebt habe.Wir führten Aktualisierungen und Einfügungen durch, bei denen die Quelltabelle nur einen Bruchteil der Anzahl an Zeilen wie die Zieltabelle aufwies, nämlich mehrere Millionen.

Als wir die Quelltabellendatensätze über das gesamte Betriebsfenster hinweg kombinierten und dann MERGE nur einmal durchführten, konnten wir eine Leistungssteigerung von 500 % feststellen.Meine Erklärung dafür ist, dass Sie für die Vorabanalyse des MERGE-Befehls nur einmal bezahlen und nicht immer wieder in einer engen Schleife.

Darüber hinaus bin ich sicher, dass das Zusammenführen von 1,6 Millionen Zeilen (Quelle) zu 7 Millionen Zeilen (Ziel) im Gegensatz zu 400 Zeilen zu 7 Millionen Zeilen über 4000 verschiedene Vorgänge (in unserem Fall) die Fähigkeiten der SQL Server-Engine viel besser nutzt.Auch hier liegt ein beträchtlicher Teil der Arbeit in der Analyse der beiden Datensätze, und diese wird nur einmal durchgeführt.

Eine weitere Frage, die ich stellen muss, ist, ob Sie sich darüber im Klaren sind, dass der Befehl MERGE mit Indizes sowohl für die Quell- als auch für die Zieltabelle viel besser funktioniert.Ich möchte Sie auf folgenden Link verweisen:

http://msdn.microsoft.com/en-us/library/cc879317(v=SQL.100).aspx

Aus persönlicher Erfahrung besteht das Hauptproblem bei MERGE darin, dass die Seitensperre jegliche Parallelität in Ihren an eine Tabelle gerichteten INSERTs ausschließt.Wenn Sie also diesen Weg einschlagen, ist es von grundlegender Bedeutung, dass Sie alle Aktualisierungen, die in eine Tabelle gelangen, in einem einzigen Writer bündeln.

Zum Beispiel:Wir hatten eine Tabelle, bei der INSERT wahnsinnige 0,2 Sekunden pro Eintrag benötigte, wobei die meiste Zeit scheinbar für die Transaktionssperre verschwendet wurde. Deshalb haben wir auf MERGE umgestellt und einige schnelle Tests zeigten, dass wir damit 256 Einträge in 0,4 Sekunden einfügen konnten oder sogar 512 in 0,5 Sekunden, wir haben dies mit Lastgeneratoren getestet und alles schien in Ordnung zu sein, bis es in Produktion ging und alles auf den Seitensperren völlig blockierte, was zu einem viel geringeren Gesamtdurchsatz als bei den einzelnen INSERTs führte.

Die Lösung bestand darin, nicht nur die Einträge von einem einzelnen Produzenten in einem MERGE-Vorgang zu bündeln, sondern auch den Stapel von Produzenten zu bündeln, die in einem einzigen MERGE-Vorgang über eine zusätzliche Warteschlangenebene (zuvor auch eine einzelne Verbindung pro DB) zu einzelnen Datenbanken gingen. aber wir nutzten MARS, um alle Aufrufe des Produzenten an die gespeicherte Prozedur zu verschachteln, die die eigentliche MERGE-Transaktion ausführte), auf diese Weise konnten wir dann viele tausend INSERTs pro Sekunde problemlos verarbeiten.

Es ist immer ein absolutes Muss, die NOLOCK-Hinweise für alle Ihre Front-End-Lesevorgänge zu haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top