あるテーブルから別のテーブルに 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
、クエリの期間についてユーザーを示します。