【发布时间】:2013-06-27 19:16:01
【问题描述】:
我需要将 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 条记录)。如果我只在一次迭代后休息 - 执行时间是 9 秒。我假设总执行时间是 9*13 秒,但还是一样的 13 分钟!
知道为什么吗?
注意:我尝试使用 CTE 而不是临时表 #CURRENT_KEYS,但结果相同。
更新一些等待统计信息。
我在等待统计中显示此过程 PAGEIOLATCH_SH 和有时 PREEMPTIVE_OS_WRITEFILEGATHER 偶尔超过 500 毫秒,但通常 suspended。
【问题讨论】:
-
您是否测量了任何等待统计数据并查看需要 13 分钟的时间?可能是日志自动增长、tempdb 数据文件、阻塞,谁知道?
-
@AaronBertrand 不太清楚怎么做,我不是 DBA,优化经验很少
-
你may find this a useful read。或者您雇用的具有优化经验的人。 :-) 你试过在循环中使用事务吗?
-
谢谢,我会研究这篇文章。我尝试通过事务以及整个循环围绕内部插入 - 没有效果。
-
问题:临时表中的插入也会被记录吗?
标签: sql-server tsql optimization insert-select