Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie kann ich eine große Flatfile mit SSIS in eine Datenbanktabelle laden?

Angenommen, Sie verwenden SQL Agent (oder einen ähnlichen Planer)

Anforderungen 1/4) Ich würde einen Vorläuferschritt haben, der die FTP- und/oder Dateikopierschritte handhabt. Ich mag es nicht, meine Pakete mit Dateimanipulationen zu überladen, wenn ich es vermeiden kann.

Erfordernisse 2/3) Auf der Ablaufsteuerungsebene wird das Paketdesign wie eine Aufgabe zum Ausführen von SQL aussehen, die mit einem Datenfluss verbunden ist, der mit einer anderen Aufgabe zum Ausführen von SQL verbunden ist. Wie @AllenG angegeben hat, werden Sie am besten bedient, indem Sie über die Datenflussaufgabe in eine Staging-Tabelle laden. Der erste Task „SQL ausführen“ löscht alle Zeilen aus der Staging-Tabelle (TRUNCATE TABLE dbo.DAILY_STAGE)

Das ungefähre Tabellendesign sieht so aus. Die Tabelle MICHAEL_BORN ist Ihre vorhandene Tabelle und die Tabelle DAILY_STAGE ist der Ort, an dem Ihr Datenfluss landen wird.

CREATE TABLE DBO.MICHAEL_BORN
(
    ID int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED
,   ItemID int NOT NULL
,   ItemName varchar(20) NOT NULL
,   ItemType varchar(20) NOT NULL
)
CREATE TABLE dbo.DAILY_STAGE
(
    ItemID int NOT NULL PRIMARY KEY CLUSTERED
,   ItemName varchar(20) NOT NULL
,   ItemType varchar(20) NOT NULL
)

Zu Demonstrationszwecken lade ich die obigen Tabellen mit Beispieldaten über TSQL

-- Original data
INSERT INTO
    dbo.MICHAEL_BORN
VALUES
    (2345,'Apple','Fruit')
,   (4578, 'Bannana','Fruit')


-- Daily load runs
-- Adds a new fruit (pear), corrects misspelling of banana, eliminates apple
INSERT INTO
    dbo.DAILY_STAGE
VALUES
    (7721,'Pear','Fruit')
,   (4578, 'Banana','Fruit')

Der Task „SQL ausführen“ nutzt den MERGE -Anweisung, die in den Editionen 2008+ von SQL Server verfügbar ist. Bitte beachten Sie, dass das abschließende Semikolon Teil der MERGE-Anweisung ist. Wenn Sie es nicht einschließen, führt dies zu einem Fehler "Eine MERGE-Anweisung muss mit einem Semikolon (;) abgeschlossen werden."

-- MERGE statement
-- http://technet.microsoft.com/en-us/library/bb510625.aspx
-- Given the above scenario, this script will
-- 1)  Update the matched (4578 bannana/banana) row
-- 2)  Add the new (pear) row
-- 3)  Remove the unmatched (apple) row

MERGE
    dbo.[MICHAEL_BORN] AS T
USING
(
    SELECT
        ItemID
    ,   ItemName
    ,   ItemType
    FROM
        dbo.DAILY_STAGE

) AS S
ON T.ItemID = S.ItemID
WHEN
    MATCHED THEN
    UPDATE
    SET
        T.ItemName = S.ItemName
    ,   T.ItemType = S.ItemType
WHEN
    NOT MATCHED THEN
    INSERT
    (
        ItemID
    ,   ItemName
    ,   ItemType
    )
    VALUES
    (
        ItemID
    ,   ItemName
    ,   ItemType
    )
WHEN
    NOT MATCHED BY SOURCE THEN
    DELETE
    ;

Anf. 5) Die Effizienz hängt vollständig von Ihren Daten und der Breite Ihrer Zeilen ab, sollte jedoch nicht schrecklich sein.

-- Performance testing
-- Assumes you have a similar fast row number generator function
-- http://billfellows.blogspot.com/2009/11/fast-number-generator.html

TRUNCATE TABLE dbo.MICHAEL_BORN
TRUNCATE TABLE dbo.DAILY_STAGE

-- load initial rows
-- 20ish seconds
INSERT INTO
    dbo.MICHAEL_BORN
SELECT
    N.number AS ItemID
,   'Spam & eggs ' + CAST(N.number AS varchar(10)) AS ItemName
,   'SPAM' AS ItemType
--, CASE N.number % 2 WHEN 0 THEN N.number + 1000000 ELSE N.number END AS UpTheEvens
FROM
    dbo.GenerateNumbers(1000000) N


-- Load staging table
-- Odds get item type switched out
-- Evens get delete and new ones created
-- 20ish seconds
INSERT INTO
    dbo.DAILY_STAGE
SELECT
    CASE N.number % 2 WHEN 0 THEN N.number + 1000000 ELSE N.number END AS ItemID
,   'Spam & eggs ' + CAST(N.number AS varchar(10)) AS ItemName
,   CASE N.number % 2 WHEN 0 THEN 'SPAM' ELSE 'Not much spam' END AS ItemType
FROM
    dbo.GenerateNumbers(1000000) N


-- Run MERGE statement, 32 seconds 1.5M rows upserted
-- Probably fast enough for you