在SQL Server中将表的一部分批量复制到自身

时间:2012-08-14 06:40:49

标签: sql-server bulkinsert

我有一些数据的“版本控制”表,每个版本将有150万行,结构是:

[ID] bigint,
[version] int,
[somecolumn] int,
[anothercolumn] int,
[thirdcolumn] tinyint

我经常需要将一个版本复制到另一个版本中,就像这个查询一样:

INSERT INTO myTable 
    (SELECT ID, version + 1, somecolumn, anothercolumn, thirdcolumn 
     FROM myTable 
     WHERE version = @version)

但问题是,这表现得相当慢,每次操作超过10秒。什么是使这项操作像闪电一样快的最佳方法?我已经尝试过选择临时表并从那里合并但是没有做得更快..

3 个答案:

答案 0 :(得分:1)

一些想法:

  1. 使用临时表不太可能有所帮助。那将是魔术。
  2. 使用NOLOCK不太可能有所帮助。我看不出任何证据表明这是一个阻塞问题,因为只有一个并发事务(至少在测试系统上)。
  3. 不确定为什么重建索引比维护它更快。你的表可能只有很少的版本?如果你得到很多,索引重建将变得越来越慢。这不是一个长期的解决方案。
  4. 尝试将聚集索引键更改为(版本,ID),以便插入是顺序的。随机DML比顺序DML慢得多。

答案 1 :(得分:0)

您是否在版本列中添加了索引?这应该加快速度。

CREATE INDEX IDX_tableName_VERSION ON tableName (version)

<强>更新

如何在桌面上使用NOLOCK读取?如果您认为您可以从针对该表的其他事务中获取系统中的脏读,则无效。我之前已经取得了一些成功,只需要小心使用它!

INSERT INTO myTable 
    (SELECT ID, version + 1, somecolumn, anothercolumn, thirdcolumn 
     FROM myTable WITH(NOLOCK)
     WHERE version = @version)

答案 2 :(得分:0)

看看是否有效。

begin
  SELECT ID, version + 1, somecolumn, anothercolumn, thirdcolumn 
  into #temp
  FROM myTable 
  WHERE version = @version

  ALTER INDEX IDX_tableName_VERSION ON tableName.version DISABLE 

  INSERT INTO myTable
  select * from #temp

  ALTER INDEX IDX_tableName_VERSION ON tableName.version ENABLE 

end