2010-09-08 7 views
7

Ich habe es mit Stücken von Daten zu tun, die jeweils 50k Zeilen sind. ich sie in eine SQL-Datenbank einfügen Verwendung von LINQ:Faster SQL Inserts?

for(int i=0;i<50000;i++) 
{ 
    DB.TableName.InsertOnSubmit 
    (
     new TableName 
     { 
      Value1 = Array[i,0], 
      Value2 = Array[i,1] 
     } 
    ); 
} 
DB.SubmitChanges(); 

Diese ca. 6 Minuten in Anspruch nimmt, und ich will es viel weniger nehmen, wenn möglich. Irgendwelche Vorschläge?

+0

Haben Sie profiliert, um zu sehen, wo die meiste Zeit verbracht wird? –

+0

13,88 Einsätze pro Sekunde sieht aus wie sehr schlechte Leistungen! Was ist deine Datenbank? –

+0

Ich habe ein sehr primitives Profiling für mein gesamtes Programm gemacht und das Einfügen dauert 95% der Zeit.Ich habe nicht innerhalb der Einfügung profiliert. – sooprise

Antwort

10

Wenn Sie in einer Datei lesen, würden Sie besser mit BULK INSERT (Transact-SQL) arbeiten und wenn Sie so viel (50K Zeilen) auf einmal aus dem Speicher schreiben, könnten Sie besser zuerst in eine flache Datei schreiben und dann verwenden Bulk Fügen Sie diese Datei ein.

+0

Ich stimme völlig zu! – Stefan

+4

Aboslutely, das Problem ist 50K einzelne Einsätze Vice One Bulk-Einsatz, das ist eine Aufgabe, die Sie einfach nicht mit LINQ tun sollten. Dies ist etwas, das in einem Set gemacht werden sollte. BULK-Insert sollte dies in weniger als einer Minute erledigen. Ich habe 21 Millionen Datensätze in 16 Minuten auf einem alten langsamen Server in großen Mengen eingefügt. – HLGEM

+0

In welchem ​​Format muss die Datei gespeichert sein? Kann ich einfach die Werte trennen? – sooprise

1

Da Sie eine einfache einfügen und nicht viel von der Verwendung von LinqToSql gewinnen, werfen Sie einen Blick auf SqlBulkCopy, wird es die meisten Rundreisen entfernen und reduzieren den Overhead auf der Sql-Server-Seite. Sie müssen nur wenige Codierungsänderungen vornehmen, um es zu verwenden.

Überprüfen Sie auch, ob Ihre Daten nach der Spalte sortiert sind, in der die Tabelle indiziert ist, da dies zu besseren Cache-Treffern führt, wenn SQL-Server die Tabelle aktualisiert.

Denken Sie auch darüber nach, ob Sie die Daten in eine temporäre Tabelle, die nicht indiziert ist, hochladen und dann eine gespeicherte Prozedur in die Haupttabelle mit einer einzigen SQL-Anweisung einfügen. Diese Mai lassen SqlServer die Indizierung über alle Ihre CPUs zu verbreiten.

1

Es gibt eine Menge Dinge, die Sie überprüfen müssen.

  1. Wie viel Speicherplatz ist der Datenbank zugeordnet? Ist genug frei, um alle Einsätze zu machen, ohne dass die Größe automatisch zunimmt? Wenn nicht, erhöhen Sie die Größe der Datenbankdatei, da so viele Einfügungen gestoppt werden müssen, um die Größe der Datenbank selbst zu verändern.

  2. KEINE einzelnen Einsätze. Sie dauern viel zu lange. Verwenden Sie stattdessen entweder Tabellenwertparameter (SQL 2008), SQL-Massenkopie oder eine einzelne INSERT-Anweisung (in dieser Reihenfolge der Präferenz).

  3. löschen Sie alle Indizes auf dieser Tabelle vor und neu erstellen sie nach dem Laden. Mit so vielen Beilagen werden sie wahrscheinlich sowieso zur Hölle verdammt sein.

  4. Wenn Sie Trigger haben, sollten Sie sie löschen, bis der Ladevorgang abgeschlossen ist.

  5. Haben Sie genug RAM im Datenbankserver? Sie müssen auf dem Server selbst überprüfen, ob es ALLE verfügbaren RAM verbraucht? Wenn ja, könnten Sie erwägen, einen Neustart vor dem Laden ... sql Server hat eine Tendenz, nur zu konsumieren und zu halten alles, was es bekommen kann.

  6. Entlang der RAM-Zeilen möchten wir genug RAM im Server halten, um die gesamte Datenbank im Speicher zu halten. Ich bin mir nicht sicher, ob das für Sie machbar ist oder nicht.

  7. Wie ist die Festplattengeschwindigkeit? Ist die Warteschlangentiefe ziemlich lang? Abgesehen vom Hardware-Austausch gibt es hier nicht viel zu tun.

Verwandte Themen