Fragensteller
Brauche Brainstorming: 42 Mio Daten in eine Tabelle einfügen

Frage
-
Hallo Leute,
ich brauche mal ein paar Ideen.
Ich habe eine Tabelle mit z.Zt. ca. 42 Mio. Datensätzen. Diese muß ich in eine andere Tabelle einfügen. Leider haut's mir das Log voll.
Ich hätte nur die Idee, das in Schritten zu 1 Mio. DS zu machen. In dem Fall müßte ich aber mit Join o.ä. sicherstellen, daß nur die Sätze reinkommen, die noch nicht drin sind.
Tabellenstruktur:
CREATE TABLE [data].[PIP_BalanceSheetItems]( [AsAtDate] [datetime] NOT NULL, [SourceSystemID] [varchar](10) NOT NULL, [BPBILID] [varchar](16) NOT NULL, [BPARTSNR] [varchar](5) NOT NULL, [BPOSWERT] [decimal](20, 1) NULL, [MASEINID] [varchar](5) NULL, [AKMSEHTS] [varchar](4) NULL, [SKLPTZWE] [decimal](4, 0) NULL, [BPEURWRT] [decimal](19, 2) NULL, CONSTRAINT [PK_PIP_BalanceSheetItems] PRIMARY KEY CLUSTERED ( [SourceSystemID] ASC, [AsAtDate] ASC, [BPBILID] ASC, [BPARTSNR] ASC )ON [PRIMARY] ) ON [PRIMARY]
Die Zieltabelle sieht genauso aus, nur die Feldnamen sind anders.
Das Copy-Statement sieht so aus:
INSERT INTO data.BalanceSheetItems_PREP ( AsAtDate , SourceSystemID , BalanceSheetID , BalanceSheetItemID , BalanceSheetItemValue , BalanceSheetItemDimensionLev1 , BalanceSheetItemDimensionLev2 , BalanceSheetItemScalar , BalanceSheetItemValueTeur ) SELECT AsAtDate , SourceSystemID , BPBILID , BPARTSNR , BPOSWERT , MASEINID , AKMSEHTS , SKLPTZWE , BPEURWRT FROM data.PIP_BalanceSheetItems WHERE AsAtDate = @lAsAtDate AND SourceSystemID = @lSystemID
Würde mir hier ein Einfügen in Schritten was bringen, besonders in Bezug auf das LOG? Ich müßte die Zieltabelle ja als join oder in einer Where-Bedingung mit NOT EXISTS einbauen, was das LOG ja auch wieder belastet.
Es kommt dann noch ein weiterer Schritt, wo die Daten mit ein bißchen Aufbereitung in eine weitere Tabelle geschrieben werden. Da hätte ich im Prinzip das Problem nochmal.
Plattenplatz erweitern ist keine Option ;-)
Gruß
Christa
Alle Antworten
-
Hi,
kannst du die Datensätze nicht über einen BULK Insert in die Tabelle einfügen und die Wiederherstellungoption der Datenbank vorher auf BULK INSERT stellen?
Anschließend die Wiederherstellungsoption wieder auf FULL stellen und ein Vollbackup durchführen um die Datensicherung aktuell zu haben.
Dann solltest du jedenfalls kein Problem mit dem Log haben oder?
Grüße
Oliver
-
Hi,
dann versuch einmal dein SQL Statement nicht mit einem "normalen" Insert durchzuführen, sondern mit BULK INSERT.
Die genaue beschreibung findest du hier: http://msdn.microsoft.com/de-de/library/ms188365.aspx
Dann sollte sich dein Log nicht mehr so aufblähen.
Grüße
Oliver
-
Hallo Christa,
kannst Du nicht mit Select TOP(n) mit Order by Primary Key arbeiten?
Dann holst Du Dir den maximalen Wert für die Primary Key Felder aus der Zieltabelle, in die Du eben eingefügt hast und beim nächsten Durchlauf hast Du ein
Select Top (n) *
from Tabelle
where PK-Felder > maximaler Wert
Order by PK-Felder;Nach jedem Durchgang könnte man prüfen, ob die @@Rowcount einigermaßen im gewünschten Bereich liegt und anschließend das (n) variieren.
Falls die Zieltabelle bereits Daten enthalten hat, musst Du Dir eben auf anderem Wege den maximalen PK ermitteln, den Du eingefügt hast oder einfügen würdest.
Man könnte z. B. mit der Row_Number über den Primary Key arbeiten und sich entsprechende Schritte ermitteln und merken, oder Du hast eine Vorstellung davon, wie Du die Daten aufteilen könntest, da in den PK-Feldern irgendwelche Nummernkreise verborgen sind.Aber auch die Aufteilung in Schritte bringt nur etwas, wenn Du häufig genug eine Logsicherung hinbekommst und dafür auch genügend Platz zur Verfügung steht.
Eine andere Alternative könnte das Trace Flag 610 sein.
http://www.insidesql.org/blogs/cmu/sql_server/trace-flag-610
Kurfassung: Das Logging ist minimal, dafür werden beim Commit die Datenseiten geschrieben und nicht das Log. Das wird wahrscheinlich langsamer sein.
Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP
www.insidesql.org/blogs/cmu -
Hallo Christoph,
ja, der Schlüssel wäre zum aufteilen der Daten geeignet. Ich müßte nur eruieren, wie das am sinnvollsten ist.
Ich befürchte nur, daß ich damit zwar das LOG weniger belaste, dafür aber die tempdb stärker. Leider leigen alle Datenbanken auf den gleichen Platte (ich weiß, das ist nicht optimal, aber da habe ich keinen Einfluß drauf).
Ich brauche eine Lösung, bei der ich nicht ein Problem gegen ein anderes eintausche.Vielleicht erledigt sich das Problem aber gerade, weil ev. die Datenmenge noch drastisch eingeschränkt werden kann. Da sind wir am Verhandeln.
@Oliver
Ich kopiere von einer SQL Server Tabelle in eine andere, nicht aus einem File. Außer select into wüßte ich keine Bulk-Methode, die da ginge. Und das steht nicht zur Debatte.
-
Hallo Christa,
sorry hatte ich irgendwie überlesen :-)
Und wenn du eine neue Spalte vom Typ Timestamp zur Ursprungstabelle hinzufügst. In diese könntest du einen berechnetetn Wert (CAST(AsAtDate)) einfügen.
Somit hättest du einen Wert nach dem du sortieren und abfragen könntest.
Grüße
Oliver