4

Twitter の #sqlhelp で参照されています (解決済み - 投稿の最後にある解決策を参照してください)。

2,900 万行の新しいデータを挿入し、それらの行を 2 つの追加の列で更新​​する SSIS パッケージを高速化しようとしています。これまでのところ、パッケージはファイルを含むフォルダーをループし、フラット ファイルをデータベースに挿入し、更新を実行してファイルをアーカイブします。 追加 (@billinkc に感謝): SSIS の順序は、Foreach ループ、データ フロー、SQL タスクの実行、ファイル タスクです。

時間がかからないこと:ループ、ファイルの移動、およびテーブルの切り捨て (ステージ)。 時間がかかること:データを挿入し、以下のステートメントを実行します。

UPDATE dbo.Stage
SET Number = REPLACE(Number,',','')
## Heading ##
-- Creates temp table for State and Date
CREATE TABLE #Ref (Path VARCHAR(255))
INSERT INTO #Ref VALUES(?)

-- Variables for insert
DECLARE @state AS VARCHAR(2)
DECLARE @date AS VARCHAR(12)

SET @state = (SELECT SUBSTRING(RIGHT([Path], CHARINDEX('\', REVERSE([Path]))-1),12,2) FROM #Ref)
SET @date = (SELECT SUBSTRING(RIGHT([Path], CHARINDEX('\', REVERSE([Path]))-1),1,10) FROM #Ref)

SELECT @state
SELECT @date

-- Inserts the values into main table
INSERT INTO dbo.MainTable (Phone,State,Date)
SELECT d.Number, @state, @date
FROM Stage d

-- Clears the Reference and Stage table
DROP TABLE #Ref
TRUNCATE TABLE Stage

挿入のバッチあたりの行数と最大挿入コミット サイズを上げてみましたが、どちらもパッケージの速度には影響していないことに注意してください。

解決および追加:

数字に興味のある方へ: OP パッケージの時間は 11.75 分でした。William の手法 (この下を参照) を使用すると、9.5 分に短縮されます。確かに、2,900 万行で低速のサーバーでは、これは予想できますが、うまくいけば、これがどれほど効果的であるかの背後にある実際のデータを示しています。重要なのは、(データ フローの後の) データの更新にかなりの時間が費やされるため、データ フロー タスクでできるだけ多くのプロセスを実行し続けることです。

うまくいけば、それが同様の問題を抱えている他の誰かに役立つことを願っています。

更新 2: IF ステートメントを追加したところ、9 分から 4 分に短縮されました。SQL 実行タスクの最終的なコード:

-- Creates temp table for State and Date
CREATE TABLE #Ref (Path VARCHAR(255))
INSERT INTO #Ref VALUES(?)

DECLARE @state AS VARCHAR(2)
DECLARE @date AS VARCHAR(12)
DECLARE @validdate datetime

SET @state = (SELECT SUBSTRING(RIGHT([Path], CHARINDEX('\', REVERSE([Path]))-1),12,2) FROM #Ref)
SET @date = (SELECT SUBSTRING(RIGHT([Path], CHARINDEX('\', REVERSE([Path]))-1),1,10) FROM #Ref)
SET @validdate = DATEADD(DD,-30,getdate())

IF @date < @validdate
BEGIN
    TRUNCATE TABLE dbo.Stage
    TRUNCATE TABLE #Ref
END
ELSE
BEGIN
-- Inserts new values
INSERT INTO dbo.MainTable (Number,State,Date)
SELECT d.Number, @state, @date
FROM Stage d

-- Clears the Reference and Stage table after the insert
DROP TABLE #Ref
TRUNCATE TABLE Stage
END
4

1 に答える 1

5

私が理解しているように、フラット ファイルから ~ 29,000,000 行を読み取り、それらをステージング テーブルに書き込んでから、ステージング テーブル内の同じ 29,000,000 行を更新 (読み取り/書き込み) し、それらの 29,000,000 レコードを移動する SQL スクリプトを実行しています (読み取りステージングから nat への書き込み) を最終テーブルに送信します。

フラット ファイルから読み取り、SSIS 変換を使用してデータをクリーンアップし、2 つの追加の列を追加してから、最終的なテーブルに直接書き込むことができませんでしたか。その場合、プロセスが行う 3 回 (読み取りと書き込みを個別にカウントする場合は 6 回) ではなく、個別のデータ セットごとに 1 回だけ作業しますか?

データフローを変更して、必要なアイテムを処理中に変換し、最終テーブルに直接書き込みます。

編集

質問の SQL から、PHONE フィールドからコンマを削除してデータを変換し、現在処理されているファイルがあるファイル パスの特定の部分から STATE と Date を取得し、それらの 3 つのデータ ポイントを保存しているように見えます。 NAT テーブルに追加します。これらのことは、データ フローの派生列変換で行うことができます。

State 列と Date 列には、State と Date という 2 つの新しい変数を設定します。変数定義で式を使用して、それらを正しい値に設定します (SQL で行ったように)。Path変数が更新されたとき(あなたのループで、私は仮定します)。State 変数と Date 変数も更新されます。

派生列の変換で、State 変数を Expression フィールドにドラッグし、State という名前の新しい列を作成します。

日付について繰り返します。

PHONE 列の場合、派生列変換で次のような式を作成します。

REPLACE( [電話], ",", "" )

派生列フィールドを「電話」を置換するように設定します

出力のために、NAT テーブルへの宛先を作成し、データ フローの Phone、State、および Date 列を NAT テーブルの適切な列にリンクします。

入力に追加の列がある場合は、ソースからそれらを取り込まないことを選択できます。これは、元のデータの Phone 列のみを操作しているように見えるためです。

/編集

于 2012-11-19T22:00:43.817 に答える