2013-06-27 59 views
1

我需要从一个表中插入130万条记录到另一个表中,并且需要很长时间(超过13分钟)。经过一番研究,我发现,这是更好地做分批这种操作,所以我放在一起这样的事情(实际查询比较复杂,这里简化为简洁明快):TSQL批插入 - 数学不起作用

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分钟一样!

任何想法为什么?

注意:而不是临时表#CURRENT_KEYS,我试图使用CTE,但结果相同。

UPDATE一些等待统计。

我在这个过程中显示PAGEIOLATCH_SH有时候PREEMPTIVE_OS_WRITEFILEGATHER等待统计有时会超过500毫秒,但通常是< 100Ms。此外SP_WHO在查询期间将用户显示为suspended

+3

你测量任何等待统计数据,看看正在13分钟?可能是日志的自动增长,tempdb数据文件阻塞,谁知道? –

+0

@AaronBertrand不知道该怎么做,我不是DBA,在优化方面也没什么经验 –

+0

您[可能会发现这是一个有用的阅读](http://www.sqlperformance.com/2013/03/io-subsystem /块状删除)。或者你有聘请谁有优化经验的人。 :-)你是否尝试使用循环内的事务? –

回答

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

+0

结果也插入到临时表中,我是否还需要预先生成主DB?还有什么是建议的临时数据库大小?最初它是200Mb我把它增加到500Mb,但看不出有什么不明显的结果。 –

+0

如果主DB正在经历自动增长事件,那么是的。 tempdb的建议大小是“它取决于”,唉。我在典型的负载下对我的基准进行基准测试,并将其设置为启动时服务器负载的合理数量。 (Tempdb在负载下增长,但在启动时恢复到原始指定大小。) 有关优化tempdb的这篇文章可能会有所帮助。 http://msdn.microsoft.com/en-us/library/ms175527%28v=sql.105%29.aspx –

+0

不幸的是,没有帮助。我将TempDB和主数据库的容量都增加了一倍,这并没有影响速度。大多数时间'PAGEIOLATCH_SH'等待的时间非常短,20-50ms,它对延迟还是会产生如此巨大的影响,还是其他的东西? –