Was ist die empfohlene Stapelgröße für SqlBulkCopy?


86

Wofür ist die empfohlene Chargengröße SqlBulkCopy? Ich suche nach einer allgemeinen Formel, die ich als Ausgangspunkt für die Leistungsoptimierung verwenden kann.

Antworten:


96

Ich habe ein Importdienstprogramm auf demselben physischen Server wie meine SQL Server-Instanz. Mithilfe einer benutzerdefinierten IDataReaderDatei werden flache Dateien analysiert und mithilfe von in eine Datenbank eingefügt SQLBulkCopy. Eine typische Datei enthält ungefähr 6 Millionen qualifizierte Zeilen, durchschnittlich 5 Spalten mit Dezimal- und Kurztext, ungefähr 30 Bytes pro Zeile.

In diesem Szenario stellte ich fest, dass eine Stapelgröße von 5.000 der beste Kompromiss zwischen Geschwindigkeit und Speicherverbrauch ist. Ich habe mit 500 angefangen und mit größeren experimentiert. Ich fand, dass 5000 im Durchschnitt 2,5-mal schneller ist als 500. Das Einfügen der 6 Millionen Zeilen dauert bei einer Stapelgröße von 5.000 etwa 30 Sekunden und bei einer Stapelgröße von 500 etwa 80 Sekunden.

10.000 waren nicht messbar schneller. Durch das Verschieben auf bis zu 50.000 wurde die Geschwindigkeit um einige Prozentpunkte verbessert, aber die erhöhte Belastung des Servers lohnt sich nicht. Über 50.000 zeigten keine Geschwindigkeitsverbesserungen.

Dies ist keine Formel, aber es ist ein weiterer Datenpunkt, den Sie verwenden können.


3
Eine Sache zu berücksichtigen ist, wenn die Tabelle leer ist und Indizes hat. In diesen Fällen möchten Sie möglicherweise alles in einem Stapel hochladen, wie hier beschrieben: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "Wenn Sie Daten in großen Mengen in eine leere Tabelle mit Indizes importieren Wenn Sie die Stapelgröße angeben, wird die Tabelle nach dem ersten Stapel nicht leer. Ab dem zweiten Stapel werden die Daten vollständig protokolliert. Bei leeren indizierten Tabellen sollten Sie den Massenimport in einem einzelnen Stapel durchführen. "
Sal

SqlBulkCopy überträgt die Daten von der Quelle (z. B. DataTable) an SQL. Welche "erhöhte Auslastung des Servers" hat SqlBulkCopy? (zB 50.000)
BornToCode

29

Dies ist ein Thema, mit dem ich mich auch einige Zeit beschäftigt habe. Ich möchte den Import großer CSV-Dateien (über 16 GB, über 65 Millionen Datensätze und Wachstum) in eine SQL Server 2005-Datenbank mithilfe einer C # -Konsolenanwendung (.Net 2.0) optimieren. Wie Jeremy hat bereits darauf hingewiesen , müssen Sie einige Feinabstimmung für Ihre besonderen Umstände tun, aber ich würde Ihnen eine anfängliche Chargengröße von 500 und Testwerte sowohl oberhalb als auch unterhalb dieses empfehlen.

Ich habe in diesem MSDN-Forumsbeitrag die Empfehlung erhalten, Werte zwischen 100 und 1000 für die Stapelgröße zu testen , und war skeptisch. Als ich jedoch auf Chargengrößen zwischen 100 und 10.000 testete, stellte ich fest, dass 500 der optimale Wert für meine Anwendung war. Der Wert 500 für SqlBulkCopy.BatchSizewird auch hier empfohlen .

Lesen Sie diese MSDN-Hinweise , um Ihren SqlBulkCopy-Betrieb weiter zu optimieren . Ich finde, dass die Verwendung von SqlBulkCopyOptions.TableLock hilft, die Ladezeit zu reduzieren.


Ich würde davon ausgehen, dass das Ausführen des Massenkopierbefehls auf dem Server selbst wahrscheinlich schneller ist.
Kapitän Kenpachi

16

Wie bereits erwähnt, hängt dies von Ihrer Umgebung ab, insbesondere vom Zeilenvolumen und der Netzwerklatenz.

Persönlich würde ich damit beginnen, die BatchSizeEigenschaft auf 1000 Zeilen festzulegen und zu sehen, wie dies funktioniert. Wenn es funktioniert, verdopple ich die Anzahl der Zeilen (z. B. auf 2000, 4000 usw.), bis ich eine Zeitüberschreitung erhalte.

Andernfalls, wenn bei 1000 eine Zeitüberschreitung auftritt, reduziere ich die Anzahl der Zeilen um die Hälfte (z. B. 500), bis es funktioniert.

In jedem Fall verdopple ich (falls erfolgreich) oder halbiere (falls fehlgeschlagen) die Differenz zwischen den letzten beiden versuchten Chargengrößen, bis ich einen Sweet Spot finde.

Der andere zu berücksichtigende Faktor ist, wie lange es dauert, einen einzelnen Stapel von Zeilen zu kopieren . Zeitüberschreitungen treten auf, wenn der Stapel der zu kopierenden Zeilen die BulkCopyTimeoutEigenschaft überschreitet, die standardmäßig 30 Sekunden beträgt. Sie können versuchen, die BulkCopyTimeoutEigenschaft auf 60 Sekunden zu verdoppeln . Dies ermöglicht einen längeren Zeitraum für das Kopieren eines größeren Satzes von Stapelzeilen. Beispielsweise kann ein Stapel von 50.000 Zeilen etwa 40 Sekunden dauern, wenn das Zeitlimit von 30 Sekunden überschritten wird. Wenn Sie ihn also auf 60 Sekunden erhöhen, kann dies die Leistung verbessern.


4

Dies hängt alles von Ihrer Implementierung ab.

Welche Geschwindigkeit können Sie in Ihrem Netzwerk erwarten? Verwenden Sie es in Forms oder ASP.Net? Müssen Sie den Benutzer über den Fortschritt informieren? Wie groß ist der Gesamtjob?

Nach meiner Erfahrung führt das Ausführen von Massenkopien ohne angegebene Stapelgröße zu Zeitüberschreitungsproblemen. Ich beginne gerne mit 1000 Datensätzen und nehme von dort aus einige Anpassungen vor.


Geschwindigkeit: Variiert, WebForms: Ja, ASP.NET: Ja, Breite Tabellen: Ja, Schmale Tabellen, Ja. Tausende Zeilen: ja. Millionen von Zeilen: ja. Wenn Sie sich ein Szenario vorstellen können, mache ich es wahrscheinlich.
Jonathan Allen

1
Ich muss mich dann an meine vorherige Antwort halten. Ich glaube nicht, dass es eine Silberkugel gibt.
Jeremy

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.