Was ist der schnellste Weg, um eine große Anzahl von Zeilen einzufügen?

27

Ich habe eine Datenbank, in der ich Dateien in eine Staging-Tabelle lade. Aus dieser Staging-Tabelle habe ich 1-2 Joins, um einige Fremdschlüssel aufzulösen und diese Zeilen in die endgültige Tabelle einzufügen (die eine Partition pro Monat hat). Ich habe ungefähr 3,4 Milliarden Zeilen für Daten aus drei Monaten.

Was ist der schnellste Weg, um diese Zeilen vom Staging in den Final Table zu bekommen? SSIS-Datenflusstask (der eine Ansicht als Quelle verwendet und schnell geladen werden kann) oder Befehl IN AUSWAHL EINFÜGEN ...? Ich habe die Datenflusstask ausprobiert und kann in ungefähr 5 Stunden ungefähr 1 Milliarde Zeilen abrufen (8 Kerne / 192 GB RAM auf dem Server), was sich für mich sehr langsam anfühlt.

nojetlag
quelle
1
Befinden sich die Partitionen auf separaten Dateigruppen (und auf diesen Dateigruppen auf verschiedenen physischen Datenträgern)?
Aaron Bertrand
3
Eine wirklich gute Ressource. Der Data Loading Performance Guide . Hiermit können Sie zahlreiche Leistungsoptimierungen durchführen , z. B. TF610 aktivieren , BCP OUT / IN, SSIS usw. Sie müssen nur die Empfehlungen befolgen und in Ihrer Umgebung testen.
Kin Shah
@Aaron Ja, pro Monat ist eine Dateigruppe, 12 San-Luns angeschlossen, sodass alle Jan-Luns auf eine Luns gehen.
Nojetlag
Ja, ich habe wirklich "Festplattensätze" gemeint und hätte wahrscheinlich auch Controller erwähnen können, die gesättigt werden können.
Aaron Bertrand
@Kin hat sich das Handbuch angesehen, aber es scheint veraltet zu sein: "Das SQL Server-Ziel ist der schnellste Weg, Daten aus einem Integration Services-Datenfluss in SQL Server zu laden. Dieses Ziel unterstützt alle Massenladeoptionen von SQL Server - mit Ausnahme von ROWS_PER_BATCH . " In SSIS 2012 wird das OLE DB-Ziel für eine bessere Leistung empfohlen.
Nojetlag

Antworten:

25

Ein gemeinsamer Ansatz:

  1. Deaktivieren / Löschen von Indizes / Einschränkungen für die Zieltabelle.
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. Mit Gutschrift auf JNK können Sie dies natürlich in nReihen tun , was die Belastung des Transaktionsprotokolls verringern kann, und natürlich bedeutet, dass Sie nur von dieser Charge starten müssen, wenn eine Charge fehlschlägt. Ich habe darüber gebloggt (obwohl in Bezug auf Löschvorgänge dieselben grundlegenden Konzepte gelten): http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. Aktivieren / erstellen Sie Indizes / Einschränkungen für die Zieltabelle erneut (und möglicherweise können Sie einige davon verschieben, wenn sie nicht für alle Vorgänge erforderlich sind und es wichtiger ist, die Basisdaten schnell online zu stellen).

Wenn Ihre Partitionen physisch und nicht nur logisch sind, können Sie Zeit gewinnen, indem verschiedene Prozesse verschiedene Partitionen gleichzeitig füllen (dies bedeutet natürlich, dass Sie TABLOCK/ nicht verwenden können TABLOCKX). Dies setzt voraus, dass die Quelle auch für die Auswahl mehrerer Prozesse ohne Überlappung / Sperrung usw. geeignet ist und diese Seite der Operation noch langsamer wird (Hinweis: Erstellen Sie einen Clustered-Index für die Quelle, der dem Partitionsschema für das Ziel entspricht).

Sie können auch etwas viel primitiveres in Betracht ziehen, wie BCP OUT/BCP IN .

Ich weiß nicht, dass ich zu SSIS springen würde, um dabei zu helfen. Es gibt wahrscheinlich einige Effizienzvorteile, aber ich weiß nicht, dass der Aufwand die Einsparungen rechtfertigt.

Aaron Bertrand
quelle
2
Löschen Sie die Indizes (insbesondere den Clustered-Index) nicht blind, wenn Ihre Daten nicht sortiert sind. Das Löschen des Index und die Erwartung, einen Clustered-Index neu zu erstellen, kann ein großer Fehler sein, da dies sowohl großen Speicherplatz als auch viel Zeit kosten kann. Ich bin nicht der erste, der einen solchen Fehler erlebt. Lesen Sie die Beschreibung von "Plan B" in diesem Artikel unter sqlmag.com/t-sql/… . Der Autor hatte das gleiche Problem.
Jyao
10

Wenn Sie Ihr Problem aus der Sicht von SSIS betrachten, ist der Grund, warum dies möglicherweise so lange gedauert hat, der, dass Sie keine Stapelverarbeitung durchgeführt haben. Dies kann dazu führen, dass zu viele Zeilen die SSIS-Pipeline füllen und die SSIS-Leistung dadurch beeinträchtigt wird. Sie müssen lediglich Ihre Zeilen pro Batch-Einstellung und möglicherweise Ihre maximale Einfügungs-Commit-Größe ändern. Was Sie nun auch hier einstellen, hängt davon ab, wie viel Speicher auf Ihrem SSIS-Server verfügbar ist. Wie hoch ist die Festplattengeschwindigkeit Ihrer SQL Server-Instanz? Der beste Weg, dies zu tun, ist ein Test. Lässt zum Beispiel 10.000 verwenden. Dadurch wird ein Stapel zu einem Zeitpunkt von 10.000 an den Server gesendet, sodass sich Ihre Pipeline nicht überfüllt und dieser Prozess schneller ausgeführt werden kann. Diese Einstellungen werden in Ihrem OLEDB-Ziel festgelegt.

OLEDB-Ziel

Wenn es ein Problem ist, können Sie auch vor und nach dem Ausführen eine SQL-Task hinzufügen, wie @AaronBertrand vorschlägt, und alle Indizes oder Einschränkungen der Tabelle entfernen / neu hinzufügen.

Zane
quelle
1
Es gibt eine ausgezeichnete Frage darüber, was "schnelles Laden" an anderer Stelle in DBA.SE bedeutet: dba.stackexchange.com/questions/141430/… .
Jon of All Trades