Laden und Transaktionsprotokoll von Massendaten


7

Ich arbeite derzeit an einem Projekt, bei dem Massenimportdaten aus Flatfiles (CSV) ungefähr 18 verschiedene Dateien enthalten, die jeweils über eine gespeicherte Prozedur mit einer bestimmten Tabelle verknüpft sind.

Ich habe die Schritte im Handbuch zur Leistung beim Laden von Daten ausgeführt .

Die Datenbank befindet sich im BulkLoggedWiederherstellungsmodus, um die Protokollierung zu minimieren. Wenn Sie die unten gespeicherte Prozedur in einer Datei mit 600000 Zeilen ausführen, wird eine Fehlermeldung angezeigt

Meldung 9002, Ebene 17, Status 4, Prozedur SP_Import__DeclarationClearanceHistory_FromCSV, Zeile 34
Das Transaktionsprotokoll für die Datenbank ist voll. Informationen dazu, warum Speicherplatz im Protokoll nicht wiederverwendet werden kann, finden Sie in der Spalte log_reuse_wait_desc in sys.databases

(Zu Testzwecken mache ich eine vollständige Sicherung, bevor ich mit dem Import beginne).

Beim Betrachten log_reuse_wait_descsehe ich folgendes:

log_reuse_wait_desc PRÜFPUNKT . Alle anderen Importe werden erfolgreich importiert.

Jeder Beitrag zur Lösung dieses Problems wäre zu begrüßen.

PROCEDURE [dbo].[SP_Import_DeclarationClearanceHistory_FromCSV]
    @FilePath [nvarchar](1000)
AS
BEGIN
    -- Creating a Temproary Table for importing the data from csv file.
    DBCC TRACEON(610)

    CREATE TABLE #DeclarationClearanceHistory
    (
          [ItemID] [int] IDENTITY(1, 1) NOT NULL ,
          [CMSDeclarationID] [bigint] NOT NULL ,
          [StatusCode] [nvarchar](10) NOT NULL ,
          [SubStatus] [nvarchar](10) NULL ,
          [DepartmentCode] [nvarchar](10) NULL ,
          [StartDate] [datetime] NULL ,
          [EndDate] [datetime] NULL ,
          PRIMARY KEY CLUSTERED ( [ItemID] ASC )
            WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                   IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
                   ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
        )
    ON  [PRIMARY]

    -- Inserting all the from csv to temproary table using BULK INSERT
    EXEC ('BULK INSERT #DeclarationClearanceHistory
    FROM ''' + @FilePath + '''
    WITH ( FIELDTERMINATOR = ''<,>'', ROWTERMINATOR =''\n'', FIRSTROW = 2, KEEPIDENTITY, CODEPAGE = ''ACP'', ORDER = ''ITEMID ASC'' );') ;

    -- By using MERGE statement, inserting the record if not present and updating if exist.
    MERGE dbo.DeclarationClearanceHistory AS TargetTable                            -- Inserting or Updating the table.
        USING #DeclarationClearanceHistory AS SourceTable                           -- Records from the temproary table (records from csv file).
        ON ( TargetTable.ItemID = SourceTable.ItemID )      -- Defining condition to decide which records are alredy present
        WHEN NOT MATCHED BY TARGET 
            THEN INSERT (
                          ItemID ,
                          CMSDeclarationID ,
                          StatusCode ,
                          SubStatus ,
                          DepartmentCode ,
                          StartDate ,
                          EndDate
                        )
               VALUES   ( SourceTable.ItemID ,
                          SourceTable.CMSDeclarationID ,
                          SourceTable.StatusCode ,
                          SourceTable.SubStatus ,
                          SourceTable.DepartmentCode ,
                          SourceTable.StartDate ,
                          SourceTable.EndDate
                        )
        WHEN MATCHED -- If  matched then UPDATE
            THEN UPDATE
               SET      TargetTable.ItemID = SourceTable.ItemID ,
                        TargetTable.CMSDeclarationID = SourceTable.CMSDeclarationID ,
                        TargetTable.StatusCode = SourceTable.StatusCode ,
                        TargetTable.SubStatus = SourceTable.SubStatus ,
                        TargetTable.DepartmentCode = SourceTable.DepartmentCode ,
                        TargetTable.StartDate = SourceTable.StartDate ,
                        TargetTable.EndDate = SourceTable.EndDate ;
DBCC TRACEOFF(610)
END

Antworten:


4

Mein erster Kommentar ist, dass Sie eine ELT (Extrahieren, Laden, Transformieren) anstelle einer ETL (Extrahieren, Transformieren, Laden) ausführen. Während ELTs satzbasierte relationale Vorteile nutzen und sehr schnell sein können, sind sie manchmal sehr schreibintensiv (speicherintensiv). Insbesondere das T-Log. Dies liegt daran, dass die Transformation auf der Festplatte durchgeführt wird (normalerweise ein Update oder Einfügen). Ich bevorzuge ETL, wenn möglich, da die Transformation im Puffer durchgeführt wird und bei korrekter Ausführung nur minimale T-Log-Schreibvorgänge erfordert. Puffer ist billig. Schnelle Speicherung gibt es nicht. Bei einigen Massenvorgängen ist das T-Protokoll ein nicht wertschöpfender Engpass.

Hier sind ein paar Dinge, die Sie tun, aber ich würde es nicht empfehlen.

  1. Massenladen in Tempdb. Ich würde empfehlen, das Massenladen einer realen Tabelle in der Zieldatenbank durchzuführen. Dann können Sie die Größe Ihrer Dateien entsprechend anpassen und müssen sich keine Sorgen über die Auswirkungen auf Tempdb machen.
  2. Unabhängige Verfahren bündeln. Teilen Sie diese beiden Verfahren auf. Die Massenlast und die Zusammenführung sind unabhängig voneinander. Durch die Aufteilung in einzelne Verfahren sind sie modularer / einheitlicher testbar.

Es sieht so aus, als hätten Sie die minimalen Protokollierungsregeln ziemlich gut abgedeckt. Sie laden mit tf 610, dem angegebenen Bestellschlüssel, im Massenprotokollierungsmodus in einen leeren B-Baum ohne Nicht-Cluster. Außerhalb der temporären Tabelle sieht hier alles in Ordnung aus. Solange die Datei tatsächlich nach dem Schlüssel sortiert ist, sollten Sie gut sein. Öffnen Sie das Protokoll in Tempdb oder in der Benutzerdatenbank?

Auf der Zusammenführungsanweisung:

UPDATES werden immer vollständig protokolliert. Ändern Sie einen ziemlich bedeutenden Teil Ihres Tisches? In diesem Fall können Sie die Zusammenführung im Speicher (SSIS-Datenflusstask oder .Net) und das Massenladen in eine neue Tabelle in Betracht ziehen. Dies ist mehr Arbeit, aber der größte Teil der Arbeit wird im Puffer erledigt und es wird ein minimales t-Protokoll verwendet. Eine minimal protokollierte Einfügung kann schneller sein als eine vollständig protokollierte Aktualisierung, wenn der Teil der Änderung erheblich ist.

Da Sie tf 610 verwenden, kann die Einfügung bei Verwendung eines Tablock-Hinweises nur minimal protokolliert werden. Weitere Informationen zum Zusammenführen mit Tablock finden Sie hier: http://blogs.msdn.com/b/sqlserverstorageengine/archive/2010/06/03/minimal-logging-and-merge-statement.aspx Hinweis: Das Update wird weiterhin ausgeführt vollständig protokolliert, wenn Sie diese Route gehen.


Danke für die Antwort. Der bereitgestellte Link erweist sich als nützlich, ich werde es gleich versuchen. Ich habe ihn jedoch zum Testen einer echten Tabelle erstellt, um festzustellen, ob Gewinne gefunden werden konnten. Mit der folgenden Anweisung DBCC TRACEON (610) BULK INSERT Temp_DeclarationClearanceHistory FROM 'DeclarationClearanceHistory.csv' WITH (FIELDTERMINATOR = '<,>', ROWTERMINATOR = '\ n', FIRSTROW = 2, KEEPIDENTITY, CODEPAGE = 'ACP (ITEMID ASC)); DBCC TRACEOFF (610) Aber ich erhalte immer noch den gleichen Fehler mit der Meldung log_reuse_wait_desc, dass log-backup angezeigt wird, während die vollständige Sicherung zuvor durchgeführt wurde
Raymond

Haben Sie die Verfahren aufgeteilt? Welches knallt das Protokoll? Die Masseneinfügung oder die Zusammenführung?
Brian

Ja, ich habe die Prozeduren aufgeteilt. Die Masseneinfügung ist diejenige, die das Benutzerdatenbankprotokoll öffnet.
Raymond

1
Ich glaube, ich sehe das Problem. Ich bin mir nicht sicher, wie ich das gesehen habe. Der Masseneinsatz verwendet nicht die Tablock-Option. msdn.microsoft.com/en-us/library/ms190422.aspx TABLOCK ist das zweite Aufzählungszeichen der Voraussetzungen.
Brian

1
Es ansehen. Aber ich konnte erfolgreich importieren, indem ich einen expliziten Checkpoint in die Speicherprozedur vor dem Zusammenführen einfügte, wie Thomas Stringer erwähnte, und die Datei in 2 aufteilte. Ich integriere derzeit die physische Temp-Tabelle. Ich hoffe, es wäre besser.
Raymond

4

Wenn Sie CHECKPOINTals log_reuse_wait_desc für diese Datenbank sehen, liegt dies daran, dass seit dem letzten Abschneiden des Protokolls kein Prüfpunkt aufgetreten ist.

Sie können dieses Problem beheben, indem Sie einen CHECKPOINTBefehl manuell starten .

Unterstützende Referenzen :
Faktoren, die die Prüfpunkte für das Abschneiden von Protokollen verzögern können,
und der aktive Teil des Protokolls


Danke für die Antwort. Beim Lesen des zweiten bereitgestellten Links wurde erwähnt, dass der Prüfpunkt erstellt wird, wenn "eine minimal protokollierte Operation in der Datenbank ausgeführt wird; beispielsweise wird eine Massenkopieroperation für eine Datenbank ausgeführt, die das Massenprotokollierungs-Wiederherstellungsmodell verwendet." . Geschieht nicht was mit der Kombination aus: Trace 610, Massenprotokollierte Wiederherstellung und Masseneinfügung?
Raymond
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.