Bulk Insert von innen von Tisch zu Tisch

Ich verwende ein A / B / View-Szenario, was bedeutet, dass die view auf Tabelle A verweist, während Tabelle B aktualisiert wird, dann tritt ein Schalter auf und die view zeigt auf Tabelle B, während Tabelle A geladen ist und so weiter. Der Schalter tritt täglich auf. Es gibt Millionen von Reihen und Tausenden von Nutzern. Ich bin auf SQL server 2012.

Meine Frage ist, wie man data in eine Tabelle von einer anderen Tabelle in der schnellstmöglichen Weise (innerhalb eines gespeicherten proc) insert. Gibt es eine Möglichkeit, BULK INSERT zu benutzen? Oder, benutzt regelmäßige Einfügung / wählen Sie den schnellsten path zu gehen?

Sie konnten zu einem ColA, ColB in DestTable_New von SrcTable wählen. Sobald DestTable_New geladen ist, erstellen Sie Indizes und Constraints neu.

Dann benennen Sie DestTable zu DestTable_Old um und benennen Sie DestTable_New zu DestTable um. Umbenennen ist sehr schnell. Wenn sich etwas als falsch herausgestellt hat, hast du auch eine Sicherung der vorherigen Tabelle in der Nähe (DestTable_Old).

Ich habe dieses Szenario einmal gemacht, wo wir das System laufen mussten 24/7 und mussten jeden Tag zehn Millionen Zeilen laden.

Sie können die ausgewählten Feldnamen in TableName aus der Zieltabelle ausführen, da ein paar Antworten darauf hindeuten, dass das so schnell wie möglich sein sollte (abhängig davon, wie viele Indizes Sie neu erstellen müssen usw.).

Aber ich würde vorschlagen, Synonyme zu verwenden, um den pointers von einer Tabelle zur anderen zu ändern. Sie sind sehr transparent und meiner Meinung nach sauberer als die Aktualisierung der view oder umbenennen Tabellen. Überprüfen Sie es hier .

INSERT... SELECT... funktioniert ähnlich wie bei BULK INSERT . Sie könnten SSIS verwenden, wie @GarethD sagt, aber das könnte übermäßig komplex sein, wenn Sie nur Zeilen von table1 zu table2 kopieren.

Wenn Sie ernsthafte datamengen kopieren, halten Sie ein Auge auf das Transaktionslog – es kann sich ziemlich schnell aufblasen, wenn Sie riesige Einsätze machen. Ein Work-around ist, die data, die Sie insert, zu "chunkify", indem Sie über ein Insert-Statement, das verarbeitet, sagen, nur 100.000 oder 10.000 Zeilen pro time (hängt davon ab, wie breit Ihre Zeilen sind, dh wie viele MB pro Pass).

(Nur neugierig, machst du ALTER VIEW , um die view zurückzusetzen? Ich habe mal etwas Ähnliches gemacht, obwohl wir vier Tische und vier viewen haben mussten, um Vergangenheit / Gegenwart / Nächste / Swap-Sets zu unterstützen.)

Ich wäre geneigt, SSIS zu benutzen.

Machen Sie Tabelle A eine OLEDB Quelle und Tabelle B ein OLEDB Ziel. Sie werden das Transaktionslog umgehen, um die Belastung des DB zu reduzieren. Der einzige path (ich kann denken), dies zu tun mit T-SQL ist es, das Wiederherstellungsmodell für Ihre gesamte database zu ändern, was weit von ideal ist, weil es bedeutet, dass keine transactions gespeichert sind, nicht nur die für Ihre Übertragung.

SSIS-Übertragung einrichten

Erstellen Sie ein neues Projekt und ziehen Sie eine Dataflow-Task auf Ihre Designoberfläche

Werkzeugkasten-Menü

Doppelklicken Sie auf Ihre Dataflow-Task, die Sie durch die Registerkarte datafluss führt. Ziehen Sie dann eine OLE DB-Quelle aus dem Menü "dataflussquellen" und ein OLE DB-Ziel aus dem Menü "dataflussziele"

DatenflussquellenDatenflussziele

Doppelklicken Sie auf die OLE DB-Quelle, richten Sie die Verbindung zu Ihrem server ein, wählen Sie die Tabelle aus, die Sie laden möchten, und klicken Sie auf OK. Ziehen Sie den grünen Pfeil aus der OLE DB-Quelle zum Ziel und doppelklicken Sie auf das Ziel. Richten Sie Ihren Verbindungsmanager, den Zieltabellennamen und die Spaltenzuordnungen ein, und Sie sollten gut gehen.

OLE DB-Quelldokumente auf MSDN

OLE DB Zieldokumente auf MSDN

Das kannst du einfach so machen

  select * into A from B Where [criteria] 

Hiermit wählen Sie die data aus B anhand der Kriterien aus und fügen sie in A ein, sofern die Spalten gleich sind oder Spaltennamen anstelle von * angeben können.

Ich weiß, die Frage ist alt, aber ich war auf der search nach einer Antwort auf die gleiche Frage und fand nichts wirklich hilfreich. Ja, der SSIS-Ansatz ist eine Möglichkeit, aber die Frage wollte einen gespeicherten Proc.

Zu meiner Freude habe ich (fast) die Lösung entdeckt, die die ursprüngliche Frage wollte; Du kannst es mit einem CLR SP machen.

Wählen Sie die data aus TableA in eine DataTable aus und verwenden Sie dann die WriteToserver (DataTable dt) Methode der SqlBulkCopy class mit TableB als DestinationTableName.

Der einzige leichte Nachteil ist, dass das CLR-Verfahren den externen Zugriff nutzen muss, um SqlBulkCopy zu verwenden, und funktioniert nicht mit der Kontextverbindung, also musst du ein bisschen mit permissions und Verbindungszeichenfolgen spielen. Aber hey! nichts ist jemals perfekt.

 INSERT INTO B as SELECT FROM A WHERE...