1

あるテーブルから別のテーブルに 130 万件のレコードを挿入する必要があり、非常に長い時間がかかります (13 分以上)。いくつかの調査の後、この操作をバッチで実行する方が良いことがわかったので、次のようなものをまとめました (実際のクエリはより複雑です。ここでは簡潔にするために簡略化しています)。

DECLARE @key INT; SET @key = 0; 
CREATE TABLE #CURRENT_KEYS(KEY INT)

WHILE 1=1
BEGIN
   -- Getting subset of keys
   INSERT INTO #CURRENT_KEYS(KEY)   
   SELECT TOP 100000 KEY FROM #ALL_KEYS WHERE KEY > @key
   IF @@ROWCOUNT = 0 BREAK

   -- Main Insert
   INSERT INTO #RESULT(KEY, VALUE)
   SELECT MAIN_TABLE.KEY, MAIN_TABLE.VALUE 
   FROM MAIN_TABLE INNER_JOIN #CURRENT_KEYS 
   ON MAIN_TABLE.KEY = #CURRENT_KEYS.KEY

   SELECT @key = MAX(KEY ) FROM #CURRENT_KEYS

   TRUNCATE TABLE #CURRENT_KEYS
END

私はすでに #ALL_KEYS テーブルに 130 万個のキーのインデックス付きリストを持っているので、ここでのアイデアは、JOIN と INSERT のキーの小さなサブセットをループで作成することです。上記のループは 13 回実行されます (1,300,000 レコード / バッチで 100,000 レコード)。1 回の繰り返しの後にブレークを設定すると、実行時間は 9 秒になります。合計実行時間は 9*13 秒と想定していましたが、同じ 13 分です。

理由はありますか?

注: 一時テーブル #CURRENT_KEYS の代わりに CTE を使用しようとしましたが、結果は同じでした。

UPDATEいくつかの待機統計。

私はこのプロセスを示しており、待機統計で 500 ミリ秒を超えるPAGEIOLATCH_SHこともありますPREEMPTIVE_OS_WRITEFILEGATHERが、100 ミリ秒未満になることもよくあります。また、SP_WHO はsuspended、クエリの期間についてユーザーを示します。

4

1 に答える 1

3

ディスク プレッシャが発生していると確信しています。PREEMPTIVE_OS_WRITEFILEGATHER は自動拡張イベント (データベースが大きくなる) であり、 PAGEIOLATCH_SH は、プロセスが IO 要求 (おそらくファイル拡張イベント) であるバッファーのラッチを待機していることを意味します。

http://blog.sqlauthority.com/2011/02/19/sql-server-preemptive-and-non-preemptive-wait-type-day-19-of-28/

http://blog.sqlauthority.com/2011/02/09/sql-server-pageiolatch_dt-pageiolatch_ex-pageiolatch_kp-pageiolatch_sh-pageiolatch_up-wait-type-day-9-of-28/

私がお勧めするのは、tempdb (一時テーブル用) とバッチ挿入を保持するデータベースの両方を事前に拡張することです。

http://support.microsoft.com/kb/2091024

于 2013-06-27T21:25:58.687 に答える