Zeilen werden mit SqlBulkCopy eingefügt

linq-to-sql sqlbulkcopy sql-server transactions

Frage

Ich ändere etwas von meinem Linq zu Sql-Code, um SqlBulkCopy zu verwenden, und Problem ist, dass ich zwei Einsätze von mehreren Tausenden Reihen in zwei Tabellen tun muss.

Der Dienst nimmt Ihren Stapel von 10.000 Links (importiert aus Sitemap, Backlink-Buildern usw.) und zerhackt diese in RSS-Feeds von X pro Feed für die Aggregation. Problem ist, ich habe bereits eine Tabelle von 32 Millionen Zeilen . Wenn ich Linq zu SQL-Einfügungen mache, dauert es je nach Standortverkehr zwischen 5 und 10 Minuten, 10.000 Links zu laden.

Die Struktur ist sehr einfach.

Feeds : Id bigint (PK), Titel varchar (1000), Beschreibung varchar (1000), published datetime, aggregierte datetime null, ShortCode varchar (8) [antiquated, nicht mehr eingefügt, aber für Altdaten verwendet]

Artikel: Id Bigint (PK), FeedId Bigint (FK), Titel varchar (1000), Beschreibung varchar (1000), veröffentlicht Datetime, Short varchar (8) [veraltet, nicht mehr eingesetzt, sondern für Legacy - Daten verwendet], ShortID Bigint null [nach dem Einfügen aktualisiert, um die ID zu erhalten (wird bei der Partitionierung verwendet]]

FutureItems : Id bigint (PK), FeedId bigint (FK), Titel varchar (1000), Beschreibung varchar (1000), Published datetime, ShortCode varchar (8) [antiquated, nicht mehr eingefügt, aber für Altdaten verwendet], ShortId bigint null [nach dem Einfügen aktualisiert, um die ID zu erhalten (wird bei der Partitionierung verwendet]]

OldItems : Id bigint (PK), FeedId bigint (FK), Titel varchar (1000), Beschreibung varchar (1000), Published datetime, ShortCode varchar (8) [antiquated, nicht mehr eingefügt, aber für Altdaten verwendet], ShortId bigint null [nach dem Einfügen aktualisiert, um die ID zu erhalten (wird bei der Partitionierung verwendet]]

Wenn Sie also eine Feedgröße von 20 haben, erhalten Sie 500 Einfügungen in die Tabelle "Feeds", dann 10000 in die Tabelle "Items" und dann "update runs", um die ShortId gleich der ID zu setzen. Einmal pro Tag wird ein Job ausgeführt, der die Daten in die anderen beiden Tabellen trennt und zukünftige Artikel in die Tabelle "Artikel" verschiebt.

Ich habe gelesen, dass SqlBulkCopy 20 Millionen Zeilen in Bezug auf die Minuten machen kann, aber ich kann keine guten Beispiele dafür finden, wie man es in mehrere Tabellen mit einer FK-Beschränkung tun kann.

Unser SQL Server ist ein "Monster" speziell für diese Anwendung. Es ist SQL 2008 R2 Web, Windows 2008 R2 Enterprise, 12 GB RAM, Dual 4 Core Xeons @ 2.8 GHz.

Unser Webserver ist ein Klon ohne den Datenbankservice.

Die CPU läuft beim Einfügen von Links etwa 85% und die Datenbank füllt den RAM.

Wenn SqlBulkCopy nicht gut ist, ist jeder Vorschlag willkommen, wir haben zahlende Kunden, die verrückt werden, und ich bin kein DBA, nur ein einfacher Programmierer.

Akzeptierte Antwort

SqlBulkCopy ist in der Tat schneller als gewöhnliche Inserts. Aber es ist schneller, da es einen Auftrag, der 1000 Einsätze pro Sekunde ausführt, in einen umwandeln kann, der 10000 / Sek. Wenn Sie in 10 Minuten nur 10000 Verknüpfungen herstellen können, müssen Sie andere Probleme haben, die durch Massenkopieren wahrscheinlich nicht gelöst werden können.

Sie müssen zuerst untersuchen, warum es so unglaublich lange dauert, 10000 Links einzufügen. Erst nachdem Sie das verstanden haben, können Sie einen Anruf tätigen, der bestimmt, ob der Wechsel zu SqlBulkCopy eine Lösung ist. Ich verstehe, dass Sie kein DBA sind, aber ich werde Ihnen ein Whitepaper "dbaish" zur Fehlerbehebung bei der SQL Server-Leistung empfehlen: Wartet und Warteschlangen . Dies ist keine Cookie-Cutter-Rezept-Lösung, sondern eine Methode, die Ihnen beibringt, wie Sie Performance-Engpässe in SQL Server identifizieren können.

Und um Ihre Frage zu beantworten: Wie benutzt man SqlBulkCopy, wenn es Einschränkungen gibt? Die allgemeinere Frage lautet: Wie führt man Bulk-Insert-Operationen durch, wenn Constraints vorhanden sind? Bei ernstzunehmenden Volumes werden die Constraints tatsächlich deaktiviert, die Bulk-Uploads ausgeführt und die Constraints können wieder aktiviert werden. Für einen optimierten Online-Betrieb mit minimaler Ausfallzeit (die Datenbank ist für den Zeitraum, in dem Einschränkungen deaktiviert sind, grundsätzlich inaktiv) verwendet man eine andere Strategie, nämlich lädt die Daten in Staging-Tabellen, validiert sie und schaltet sie dann mit ein Partition Switching-Operation, siehe Daten effizient übertragen mit Partition Switching .


Beliebte Antwort

Ich denke, Ihr wirkliches Problem bei der Verwendung einer einfachen Masseneinfügung besteht darin, dass Sie die Feed-IDs aus der ursprünglichen Einfügung für die anderen Tabellen benötigen. Folgendes würde ich tun. Verwenden Sie die Masseneinfügung, um sie in eine Zwischenspeichertabelle einzufügen. Verwenden Sie dann einen gespeicherten Proc, um die Einfügungen in die reale Tabelle auf einer Set-basierten Weise durchzuführen. Sie können die output-Klausel in der ursprünglichen Einfügung in die Feed-Tabelle verwenden, um eine Tabellenvariable mit den Feed-IDs zurückzuholen, die Sie für die Einfügungen in die anderen Tabellen benötigen.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum