C # - Einfügen mehrerer Zeilen mit einer gespeicherten Prozedur

8

Ich habe eine Liste von Objekten, diese Liste enthält ungefähr 4 Millionen Objekte. Es gibt einen gespeicherten Proc, der Objektattribute als Parameter verwendet, einige Suchvorgänge durchführt und sie in Tabellen einfügt.

Was ist der effizienteste Weg, diese 4 Millionen Objekte in db einzufügen?

Wie mache ich:

%Vor%

Das war wirklich langsam.

Gibt es einen besseren Weg, dies zu tun?

Dieser Prozess wird eine geplante Aufgabe sein. Ich werde diese Stunde immer ausführen, also erwarte ich hohe Datenmengen wie diese.

    
DarthVader 19.05.2010, 14:09
quelle

5 Antworten

8

Sehen Sie sich die SqlBulkCopy-Klasse

an

basierend auf Ihrem Kommentar, dump die Daten in eine Staging-Tabelle dann tun Sie die Suche und fügen Sie in den realen Tabellensatz basierend auf einem Proc .... es wird viel schneller als Zeile für Zeile

    
SQLMenace 19.05.2010, 14:11
quelle
2

Es wird niemals ideal sein, vier Millionen Datensätze aus C # einzufügen, aber ein besserer Weg, dies zu tun, besteht darin, den Befehlstext im Code zu erstellen, so dass Sie in Blöcken arbeiten können.

Dies ist kaum kugelsicher und zeigt nicht, wie man Lookups einbaut (wie Sie erwähnt haben), aber die Grundidee ist:

%Vor%     
Jeff Sternal 19.05.2010 14:26
quelle
2

Ich hatte hervorragende Ergebnisse mit XML, um große Datenmengen in SQL Server zu bekommen. Wie du, habe ich zuerst Zeilen hintereinander eingefügt, die aufgrund der Umlaufzeit zwischen der Anwendung und dem Server ewig gedauert haben, dann habe ich die Logik so umgestellt, dass sie eine XML-Zeichenfolge mit allen einzufügenden Zeilen übergibt. Die Zeit zum Einfügen ging von 30 Minuten auf weniger als 5 Sekunden. Das war für ein paar tausend Zeilen. Ich habe mit XML-Strings bis zu 20 Megabyte getestet und es gab keine Probleme. Abhängig von Ihrer Zeilengröße könnte dies eine Option sein.

Die Daten wurden als XML-String mit dem Typ nText übergeben.

So etwas bildete die grundlegenden Details der gespeicherten Prozedur, die die Arbeit verrichtet hat:

CREATE PROCEDURE XMLInsertPr (@XmlString ntext)  
DECLARE @ReturnStatus int, @hdoc int

EXEC @ReturnStatus = sp_xml_preparedocument @hdoc OUTPUT, @XmlString  
IF (@ReturnStatus & lt; & gt; 0)  
BEGINNEN  
RAISERROR ('Kann XML-Dokument nicht öffnen', 16,1,50003)  
RÜCKKEHR @ReturnStatus  
ENDE  

INSERT INTabelleName  
SELECT * FROM OPENXML (@hdoc, '/ XMLDaten / Daten') WIT TableName  
ENDE

    
John Dyer 19.05.2010 15:07
quelle
1

Sie könnten in Betracht ziehen, alle Indizes, die Sie in den Tabellen, in die Sie einfügen, einfügen, und sie dann neu zu erstellen, nachdem Sie alles eingefügt haben. Ich bin mir nicht sicher, wie die Klasse zum Massenkopieren funktioniert, aber wenn Sie Ihre Indizes für jede Einfügung aktualisieren, kann sich das etwas verlangsamen.

    
Abe Miessler 19.05.2010 14:30
quelle
0
  1. Wie bereits erwähnt: Indizes löschen (und später neu erstellen)
  2. Wenn Sie Ihren Daten vertrauen: Generieren Sie eine SQL-Anweisung für jeden Aufruf des gespeicherten Proc, kombinieren Sie einige und führen Sie sie dann aus.
    Das spart Ihnen Kommunikationsaufwand.
  3. Die kombinierten Aufrufe (zu dem gespeicherten proc) könnten in eine BEGIN TRANSACTION gehüllt werden, so dass Sie nur ein Commit pro x insert
  4. haben

Wenn es sich um einen einmaligen Vorgang handelt: Optimieren Sie es nicht und führen Sie es während der Nacht / am Wochenende aus

    
GvS 19.05.2010 14:39
quelle