2008-12-02 9 views
15

Ich versuche, eine Masse von Datensätzen in SQL Server 2005 von Vb.Net einzufügen. Obwohl das Einfügen gut funktioniert, tue ich mein Bestes, um es so schnell wie möglich zu machen. Momentan dauert es ~ 11 Minuten für 100.000 Datensätze. Was wäre der vorgeschlagene Ansatz zum Einfügen einer großen Anzahl von Datensätzen in SQL Server von einer Anwendung?Mass Insert in Sql Server

Meine aktuelle Vorgehensweise ist im Grunde die Verbindung zu öffnen, durch meine Liste von Informationen iterieren und feuern einzelne SQL einfügen Statements, und dann die Verbindung zu schließen. Hat jemand einen besseren Vorschlag, wie man das macht?

Aktuelle Funktion:

Public Sub BatchInsert(ByVal ParamCollections As List(Of SqlParameter())) 

    Dim Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection) 
    Using scope As TransactionScope = New TransactionScope() 
    Using Conn 

     Dim cmd As SqlCommand = New SqlCommand("sproc_name", Conn) 

     Conn.Open() 
     cmd.CommandType = CommandType.StoredProcedure 

     For i = 0 To ParamCollections.Count - 1 

      cmd.Parameters.Clear() 
      cmd.Parameters.AddRange(ParamCollections(i)) 
      cmd.ExecuteNonQuery() 

     Next 

     Conn.Close() 
     scope.Complete() 
    End Using 
    End Using 

End Sub 

Antwort

19

die SqlBulkCopy Klasse verwendet, wird es in der Lage sein, durch diese 100K Reihen viel schneller als einzelne Einsätze auszuführen.

Ach ja, und wenn Sie können, würde ich Sie bitten, eine IDataReader fähig Klasse zu implementieren, die SqlBulkCopy.WriteToServer(IDataReader) Verfahren zuzuführen, dies ermöglicht es Ihnen, Daten sequentiell zu erzeugen, eine Zeile zu einem Zeitpunkt. Wenn Sie beispielsweise aus einer Textdatei importieren, können Sie mithilfe von IEnumerable<T> Methoden, die yield return verwenden und in ein IDataReader Objekt konvertieren, Daten ganz natürlich an den Server übermitteln.

Um dem Verlust der Rollback-Fähigkeit mit BCP entgegenzuwirken, können Sie die Daten in eine temporäre Tabelle übertragen und anschließend normale INSERT INTO Anweisungen auf dem Server ausführen, um die Daten aus der temporären Tabelle in die Produktionstabelle zu übertragen ermöglicht es Ihnen, eine Transaktion für den letzten Übertragungsteil zu verwenden, und wird immer noch viel schneller ausgeführt als Ihre ursprünglichen individuellen Einfügeanweisungen.

EDIT: und Here's an example (C#, sollte aber leicht zu VB.Net konvertieren) der Verwendung der Massenlast-API.

+0

Solange das OP ist in Ordnung mit diese Transaktionen nicht protokollieren, das ist großartig. Durch die Verwendung von BCP wird die Möglichkeit zum Zurücksetzen der Daten beseitigt (nicht wie es die meiste Zeit ohnehin ist). – StingyJack

+0

Ich schaue jetzt in die Massenkopie. Es sieht so aus, als müsste ich meine Daten in eine DataTable konvertieren, um die Massenkopie zu nutzen. Wird der Prozess zum Erstellen und Laden der DataTable die Build-Kopie-Gewinne ausgleichen? – Nathan

+0

Nein. Die Zeit, die zum Erstellen der Datentabelle benötigt wird, ist im Vergleich zu der Zeit, die Sie gerade ausgeben, winzig. –

0

Es hängt davon ab, wie die Massenkopierklasse implementiert ist. Aber es gibt ein Befehlszeilentool, das in Installationen von SQL Server enthalten ist, die genau das tun (es ist wahrscheinlich das gleiche). Es heißt "bcp". Ich benutze es jetzt und es sollte in der Lage sein, in wenigen Sekunden 100k Zeilen zu stürmen.

Die MSDN-Dokumentation bezieht sich auf das Dienstprogramm "Massenimport".

1

Es gibt auch eine gespeicherte Proc (genannt Bulk Insert), die den Trick für Sie tun wird .. Es verwendet bcp unter den Abdeckungen.

Check diesen Link, um zu sehen Syntax

link text

2

Setzen Sie Ihre Daten in eine CSV-Datei importiert werden und das Dienstprogramm Bcp auf den Daten ausgeführt werden. Sie können nicht schneller mit sequenziellen Aufrufen von einzelnen Zeilen auf einmal, Sie benötigen ein Bulk-Dienstprogramm, wenn Sie die Leistung wollen.

Mit der SQLBulkCopy-Klasse können Sie alle Daten in einer Sammlung übertragen, sodass der Server alles auf einmal verarbeiten kann, wodurch das Hin und Her entfällt. Wenn Sie also vermeiden wollen, temporäre Dateien zu erstellen (was ich tun würde), dann schauen Sie sich diese Klasse an.

Einfach die Verbindung offen zu lassen ist ein guter Anfang, aber Sie haben immer noch den Aufwand, eine Zeile zu senden, mit SQL speichern, ein Ergebnis zurückgeben, und dann müssen Sie in die nächste Zeile durchlaufen.

11

Dank der Hilfe von allen war ich in der Lage, meine Aufgabe zu erledigen. Die SQLBulkCopy passt perfekt zu meinen Bedürfnissen (obwohl es einige andere ausgezeichnete Vorschläge gab). Mit SqlBulkcopy ging die Zeit von 11 Minuten auf 45 Sekunden. Ich kann den Unterschied nicht glauben!

Für die Zukunft, hier sind ein paar Informationen sind:

  • Um SQL Bulk Copy zu verwenden, Ihre Daten in Form eines DataSet, Datareader oder Datatable sein. Einige XML sind ebenfalls erlaubt.

Grundimplementierungscode:

Public Sub PerformBulkCopy(ByVal dt As DataTable) 

    Using Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection) 
     Conn.Open() 

     Using s As SqlBulkCopy = New SqlBulkCopy(Conn) 

      s.DestinationTableName = "TableName" 
      s.WriteToServer(dt) 
      s.Close() 

     End Using 

     Conn.Close() 
    End Using 
End Sub 

Sehr informativ Link, den ich gefunden:

Using Sql Bulk Copy

Vielen Dank an alle für die Hilfe! Ich schätze es sehr.