Aufgabe
Archivieren Sie alle bis auf einen fortlaufenden Zeitraum von 13 Monaten aus einer Gruppe großer Tische. Die archivierten Daten müssen in einer anderen Datenbank gespeichert werden.
- Die Datenbank befindet sich im einfachen Wiederherstellungsmodus
- Die Tabellen haben eine Größe von 50 Millionen Zeilen bis zu mehreren Milliarden Zeilen und nehmen in einigen Fällen jeweils Hunderte von GB ein.
- Die Tabellen sind derzeit nicht partitioniert
- Jede Tabelle verfügt über einen Clustered-Index für eine immer größer werdende Datumsspalte
- Jede Tabelle hat zusätzlich einen nicht gruppierten Index
- Alle Datenänderungen an den Tabellen sind Einfügungen
- Ziel ist es, Ausfallzeiten der Primärdatenbank zu minimieren.
- Server ist 2008 R2 Enterprise
Die Tabelle "archive" wird ungefähr 1,1 Milliarden Zeilen haben, die Tabelle "live" ungefähr 400 Millionen. Natürlich wird die Archivtabelle mit der Zeit größer, aber ich gehe davon aus, dass auch die Live-Tabelle einigermaßen schnell größer wird. Sagen wir mindestens 50% in den nächsten paar Jahren.
Ich hatte über Azure-Stretch-Datenbanken nachgedacht, aber leider befinden wir uns in Version 2008 R2 und werden wahrscheinlich noch eine Weile dort bleiben.
Derzeitiger Plan
- Erstellen Sie eine neue Datenbank
- Erstellen Sie neue Tabellen, die nach Monat (unter Verwendung des Änderungsdatums) in der neuen Datenbank partitioniert sind.
- Verschieben Sie die Daten der letzten 12 bis 13 Monate in die partitionierten Tabellen.
- Führen Sie einen Umbenennungsaustausch der beiden Datenbanken durch
- Löschen Sie die verschobenen Daten aus der jetzt "archivierten" Datenbank.
- Partitionieren Sie jede der Tabellen in der Datenbank "archive".
- Verwenden Sie Partition Swaps, um die Daten in Zukunft zu archivieren.
- Mir ist klar, dass ich die zu archivierenden Daten auslagern, diese Tabelle in die Archivdatenbank kopieren und dann in die Archivtabelle umlagern muss. Das ist akzeptabel.
Problem: Ich versuche, die Daten in die anfänglich partitionierten Tabellen zu verschieben (tatsächlich führe ich immer noch einen Proof-of-Concept-Test durch). Ich versuche, TF 610 (gemäß dem Data Loading Performance Guide ) und eine INSERT...SELECT
Anweisung zu verwenden, um die Daten zu verschieben, die anfänglich für minimal protokolliert gehalten werden. Leider ist es jedes Mal, wenn ich es versuche, vollständig protokolliert.
An diesem Punkt denke ich, dass meine beste Wette darin besteht, die Daten mit einem SSIS-Paket zu verschieben. Ich versuche das zu vermeiden, da ich mit 200 Tabellen arbeite und alles, was ich per Skript tun kann, einfach generieren und ausführen kann.
Fehlt in meinem allgemeinen Plan etwas, und ist SSIS meine beste Wahl, um die Daten schnell und mit minimaler Verwendung des Protokolls zu verschieben (Platzprobleme)?
Demo Code ohne Daten
-- Existing structure
USE [Audit]
GO
CREATE TABLE [dbo].[AuditTable](
[Col1] [bigint] NULL,
[Col2] [int] NULL,
[Col3] [int] NULL,
[Col4] [int] NULL,
[Col5] [int] NULL,
[Col6] [money] NULL,
[Modified] [datetime] NULL,
[ModifiedBy] [varchar](50) NULL,
[ModifiedType] [char](1) NULL
);
-- ~1.4 bill rows, ~20% in the last year
CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
( [Modified] ASC )
GO
-- New DB & Code
USE Audit_New
GO
CREATE PARTITION FUNCTION ThirteenMonthPartFunction (datetime)
AS RANGE RIGHT FOR VALUES ('20150701', '20150801', '20150901', '20151001', '20151101', '20151201',
'20160101', '20160201', '20160301', '20160401', '20160501', '20160601',
'20160701')
CREATE PARTITION SCHEME ThirteenMonthPartScheme AS PARTITION ThirteenMonthPartFunction
ALL TO ( [PRIMARY] );
CREATE TABLE [dbo].[AuditTable](
[Col1] [bigint] NULL,
[Col2] [int] NULL,
[Col3] [int] NULL,
[Col4] [int] NULL,
[Col5] [int] NULL,
[Col6] [money] NULL,
[Modified] [datetime] NULL,
[ModifiedBy] [varchar](50) NULL,
[ModifiedType] [char](1) NULL
) ON ThirteenMonthPartScheme (Modified)
GO
CREATE CLUSTERED INDEX [AuditTable_Modified] ON [dbo].[AuditTable]
(
[Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO
CREATE NONCLUSTERED INDEX [AuditTable_Col1_Col2_Col3_Col4_Modified] ON [dbo].[AuditTable]
(
[Col1] ASC,
[Col2] ASC,
[Col3] ASC,
[Col4] ASC,
[Modified] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ThirteenMonthPartScheme (Modified)
GO
Code verschieben
USE Audit_New
GO
DBCC TRACEON(610);
INSERT INTO AuditTable
SELECT * FROM Audit.dbo.AuditTable
WHERE Modified >= '6/1/2015'
ORDER BY Modified
quelle
Antworten:
Warum erhalten Sie keine minimale Protokollierung?
Ich habe das gefunden , dass das von Ihnen erwähnte Data Loading Performance Guide eine äußerst wertvolle Ressource ist. Es ist jedoch auch nicht zu 100% umfassend, und ich vermute, dass das Raster bereits so komplex ist, dass der Autor keine Spalte hinzugefügt hat
Table Partitioning
, um Unterschiede im Verhalten herauszustellen, je nachdem, ob die Tabelle, die die Einfügungen empfängt, partitioniert ist. Wie wir später sehen werden, scheint die Tatsache, dass die Tabelle bereits partitioniert ist, eine minimale Protokollierung zu verhindern.Empfohlener Ansatz
Basierend auf den Empfehlungen im Datenlade-Leistungshandbuch (einschließlich des Abschnitts "Massenladen einer partitionierten Tabelle") sowie umfangreichen Erfahrungen beim Laden partitionierter Tabellen mit mehreren zehn Milliarden Zeilen, würde ich diesen Ansatz empfehlen:
Die Unterschiede im Vergleich zu Ihrem ursprünglichen Ansatz:
TABLOCK
die Daten mit Hilfe der Partitionsumschaltung nach jeweils einem Monat in einen Heap laden , um sie in die partitionierte Tabelle zu verschieben.DELETE
zu räumender alter Tisch wird vollständig protokolliert. Vielleicht können Sie entwederTRUNCATE
die Tabelle löschen oder eine neue Archivtabelle erstellen.Vergleich der Ansätze zum Verschieben der Daten aus dem letzten Jahr
Um die Ansätze auf meinem Computer in angemessener Zeit zu vergleichen, habe ich einen
100MM row
Testdatensatz verwendet, den ich generiert habe und der Ihrem Schema folgt.Wie Sie aus den folgenden Ergebnissen ersehen können, werden die Protokollschreibvorgänge erheblich beschleunigt und verringert, indem Daten mithilfe des
TABLOCK
Hinweises in einen Heap geladen werden. Es gibt einen zusätzlichen Vorteil, wenn dies jeweils für eine Partition durchgeführt wird. Beachten Sie auch, dass die Methode "Eine Partition gleichzeitig" problemlos weiter parallelisiert werden kann, wenn Sie mehrere Partitionen gleichzeitig ausführen. Abhängig von Ihrer Hardware kann dies zu einem positiven Effekt führen. Normalerweise laden wir mindestens vier Partitionen gleichzeitig auf Hardware der Serverklasse.Hier ist das vollständige Testskript .
Schlussnoten
Alle diese Ergebnisse hängen zu einem gewissen Grad von Ihrer Hardware ab. Meine Tests wurden jedoch auf einem Standard-Quad-Core-Laptop mit drehendem Festplattenlaufwerk durchgeführt. Es ist wahrscheinlich, dass das Laden der Daten viel schneller sein sollte, wenn Sie einen anständigen Server verwenden, der zum Zeitpunkt der Durchführung dieses Vorgangs nicht viele andere Lasten aufweist.
Zum Beispiel habe ich den empfohlenen Ansatz auf einem tatsächlichen Entwickler-Server (Dell R720) ausgeführt und eine Reduzierung auf
76 seconds
(von156 seconds
meinem Laptop) festgestellt . Interessanterweise hat der ursprüngliche Ansatz des Einfügens in eine partitionierte Tabelle nicht die gleiche Verbesserung erfahren und wurde immer noch nur12 minutes
auf dem Entwickler-Server übernommen. Vermutlich liegt dies daran, dass dieses Muster einen seriellen Ausführungsplan ergibt und ein einzelner Prozessor auf meinem Laptop mit einem einzelnen Prozessor auf dem Entwicklungsserver übereinstimmen kann.quelle
Dies könnte ein guter Kandidat für Biml sein. Ein Ansatz wäre, eine wiederverwendbare Vorlage zu erstellen, mit der Daten für eine einzelne Tabelle in kleinen Datumsbereichen mit einem For Each-Container migriert werden. Das Biml durchläuft Ihre Tabellensammlung, um identische Pakete für jede qualifizierende Tabelle zu erstellen. Andy Leonard hat ein Intro in seiner Stairway-Serie .
quelle
Anstatt die neue Datenbank zu erstellen, können Sie die reale Datenbank auch in einer neuen Datenbank wiederherstellen und die neuesten Daten für 12 bis 13 Monate löschen. Dann löschen Sie in Ihrer realen Datenbank die Daten, die nicht in Ihrem gerade erstellten Archivbereich enthalten sind. Wenn große Löschvorgänge ein Problem darstellen, können Sie möglicherweise einfach 10 KB oder größere Sätze per Skript löschen, um dies zu tun.
Ihre Partitionierungsaufgaben scheinen nicht beeinträchtigt zu sein und nach dem Löschen auf beide Datenbanken anwendbar zu sein.
quelle