【问题标题】:TSQL Batch insert - math doesn't workTSQL 批量插入 - 数学不起作用
【发布时间】: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


【解决方案1】:

我很确定您遇到了磁盘压力。 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

【讨论】:

  • 结果也被插入到临时表中,我还需要预先增长主数据库吗?另外临时数据库的推荐大小是多少?最初是 200Mb,我将其增加到 500Mb,但没有看到明显的结果。
  • 如果主数据库正在经历自动增长事件,那么是的。 tempdb 的推荐大小是“视情况而定”,唉。我在典型负载下对我的进行基准测试,并将其设置为启动时服务器负载的合理数字。 (Tempdb 在负载下会增长,但在启动时会恢复到原来的指定大小。)这篇关于优化 tempdb 的文章可能会有所帮助。 msdn.microsoft.com/en-us/library/ms175527%28v=sql.105%29.aspx
  • 不幸的是,这没有帮助。我将 TempDB 和主 DB 的大小都增加了一倍,这并没有影响速度。大多数时候PAGEIOLATCH_SH 等待非常小 20-50 毫秒,它是否仍然会对延迟产生如此巨大的影响,还是其他原因?
  • 文件还在增长吗?插入物是否有可能以某种方式重叠导致它们相互阻塞?
  • 据我所知,文件大小与初始大小相同
猜你喜欢
  • 2011-04-07
  • 2016-09-24
  • 2014-09-17
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 2013-10-01
  • 2021-04-23
相关资源
最近更新 更多