sql >> データベース >  >> RDS >> Sqlserver

SSISを使用して大きなフラットファイルをデータベーステーブルにロードするにはどうすればよいですか?

    SQLエージェント(または同様のスケジューラー)を使用していると仮定します

    要件1/4)FTPやファイルのコピーステップを処理する先行ステップがあります。回避できるのであれば、ファイル操作でパッケージを乱雑にするのは好きではありません。

    要件2/3)制御フローレベルでは、パッケージデザインは、別のSQL実行タスクに接続されたデータフローに接続されたSQL実行タスクのように見えます。 @AllenGが示しているように、データフロータスクを介してステージングテーブルにロードするのが最適です。最初のSQL実行タスクは、ステージングテーブル(TRUNCATE TABLE dbo.DAILY_STAGE)からすべての行を削除します

    おおよそのテーブルデザインはこんな感じ。 MICHAEL_BORNテーブルは既存のテーブルであり、DAILY_STAGEはデータフローが到達する場所です。

    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
    )
    

    デモンストレーションの目的で、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')
    

    SQLの実行タスクは、MERGE を利用します。 SQLServerの2008以降のエディションで使用可能なステートメント。末尾のセミコロンはMERGEステートメントの一部であることに注意してください。これを含めないと、「MERGEステートメントはセミコロン(;)で終了する必要があります」というエラーが発生します。

    -- 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
        ;
    

    必要条件5)効率は完全にデータと行の幅に基づいていますが、ひどいものであってはなりません。

    -- 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
    


    1. SQL Server(T-SQL)で数値を通貨としてフォーマットする方法

    2. mysqli_stmt_bind_resultの奇妙な問題

    3. MySQLでパスワードをハッシュするために使用する関数は何ですか?

    4. 単一サーバーでのMysqlレプリケーション