Frage:
Ich habe ein Skript mit rund 45.000 Einfügungen aus ausgewählten Anweisungen. Wenn ich versuche, es auszuführen, erhalte ich eine Fehlermeldung, die besagt, dass mir der Speicher ausgeht. Wie kann ich dieses Skript ausführen?
Kontext:
- Einige neue Datenfelder wurden hinzugefügt, damit eine App mit einer anderen App, die der Client verwendet, gut funktioniert.
- Vom Client wurde eine Tabelle mit Daten abgerufen, die die aktuellen Datenelemente den Werten für diese neuen Felder zuordnet.
- Konvertierte Tabelle zum Einfügen von Anweisungen.
- Wenn ich nur einige der Anweisungen ausführe, funktioniert dies, das gesamte Skript jedoch nicht.
- Nein, es gibt keine Tippfehler.
Wenn es einen anderen Weg gibt, wie ich diese Daten laden soll, züchtige ich mich und lass es mich wissen.
sql-server
sql-server-2005
etl
Spaghetticowboy
quelle
quelle
Antworten:
Die maximale Stapelgröße für SQL Server 2005 beträgt 65.536 * Netzwerkpaketgröße (Network Packet Size, NPS), wobei NPS normalerweise 4 KB beträgt. Das klappt auf 256 MB. Das würde bedeuten, dass Ihre Einfügeanweisungen durchschnittlich 5,8 KB groß sind. Das scheint nicht richtig zu sein, aber vielleicht gibt es fremde Räume oder etwas Ungewöhnliches.
Mein erster Vorschlag wäre, nach jeder INSERT-Anweisung eine "GO" -Anweisung einzufügen. Dadurch wird Ihr einzelner Stapel mit 45.000 INSERT-Anweisungen in 45.000 separate Stapel aufgeteilt. Dies sollte leichter zu verdauen sein. Seien Sie vorsichtig, wenn einer dieser Einschübe versagt, kann es schwierig sein, den Schuldigen zu finden. Vielleicht möchten Sie sich mit einer Transaktion schützen. Sie können diese Anweisungen schnell hinzufügen, wenn Ihr Editor über eine gute Such- und Ersetzungsfunktion (mit der Sie nach Rückgabezeichen wie \ r \ n suchen und diese ersetzen können) oder eine Makrofunktion verfügt.
Der zweite Vorschlag besteht darin, einen Assistenten zu verwenden, um die Daten direkt aus Excel zu importieren. Der Assistent erstellt hinter den Kulissen ein kleines SSIS-Paket für Sie und führt es dann aus. Es wird dieses Problem nicht haben.
quelle
GO
nach jeder Aussage? Nun, ich denke, wenn Sie sie mit einem anderen Skript generieren, das in Ordnung ist. Ansonsten würde ich nur alle 1000INSERT
s eine setzen. Warum nicht alle Zeilen in eine temporäre Tabelle oder eine Tabellenvariable laden und sie dann von dort auf einmal in die Zieltabelle laden, um die Transaktion atomar zu machen und die Größe der Transaktion zu minimieren?BULK INSERT
oderbcp
scheinen angemessenere Optionen als 45.000 Einfügeanweisungen.Wenn Sie bei den Einfügeanweisungen bleiben müssen, würde ich ein paar Optionen in Betracht ziehen:
A: Verwenden Sie Transaktionen und verpacken Sie Stapel mit jeweils 100 oder 500 oder 1000 Anweisungen, um die Auswirkungen auf das Protokoll und den Stapel zu minimieren. z.B
B: Verwenden Sie anstelle einzelner insert-Anweisungen jeweils
UNION ALL
100 oder 500 Anweisungen, zIch habe die Fehlerbehandlung der Kürze halber weggelassen, aber der Punkt ist, dass ich niemals versuchen würde, einen einzelnen Stapel von 45.000 einzelnen Anweisungen an SQL Server zu senden.
quelle
VARCHAR(800)
Spalten im Jahr 2008 mit einer Kompilierungszeit von 12,5 Minuten auf meiner 2008-Entwicklungsinstanz eingereicht, da es viele unnötige Arbeiten zum Vergleichen von Werten ausführt, anstatt sie nur einzufügen (führt viel aus) schneller, wenn parametriert und keine Werte zu sehen). Obwohl 2012 stark verbessert, ist das nichtlineare Muster immer noch vorhanden und sollte in der Version danach behoben werden.Ich bin nicht sicher, warum Sie den Fehler "out of memory" erhalten, aber es gibt einen einfacheren Ansatz.
Wenn Sie die Daten aus der Tabelle in ein getrenntes Format (z. B. csv) exportieren können, können Sie die Daten mit dem Datenimport-Assistenten in SSMS für Sie einfügen:
quelle
Erstellen Sie mit mehreren SqlBulkCopy eine temporäre Tabelle. Fügen Sie neue Daten in die temporäre Tabelle ein und fügen Sie die Daten in der temporären Tabelle in die vorhandene Tabelle ein. Beispiel mit der C # SqlBulkCopy.WriteToServer-Methode (DataTable) . Ich hoffe es hilft
quelle
Ja, das können wir, ich habe es mit einem BCP- Ansatz (Bulk Copy Program) versucht , um ein OutOfMemory- Problem zu vermeiden .
Hinweis : Auf SQL Server 2014 ausprobiert.
In BCP müssen wir zuerst die Quellendatenbankdaten in eine BCP- Datei (im lokalen Verzeichnisordner) exportieren und dann diese BCP- Datei in die Zieldatenbank importieren .
Nachfolgend sind die Schritte für die Kuchenwanderung aufgeführt:
Hinweis:
a) Stellen Sie sicher, dass in der Zieldatenbank eine leere Tabelle vorhanden ist
b) Stellen Sie sicher, dass der Ordner Temp im Laufwerk C vorhanden ist
Erstellen Sie eine bat-Datei mit dem Namen Export_Data.bat mit dem folgenden Befehl:
Pause
Führen Sie diese bat-Datei aus. Dadurch wird eine bcp- Datei im Temp- Ordner generiert
Erstellen Sie dann eine weitere bat-Datei mit dem Namen Import_Data.bat mit dem folgenden Befehl:
Pause
Und es geht los!
quelle