将批量数据放入繁忙的表中

时间:2013-06-18 08:52:18

标签: sql-server tsql cursor

我目前正在客户端的MSSQL Server上执行分析。我已经解决了很多问题(不必要的索引,索引碎片,NEWID()用于整个商店的身份等),但我遇到了一个我以前没见过的具体情况。

进程1将数据导入到临时表中,然后进程2使用INSERT INTO从登台表复制数据。第一个过程非常快(它使用BULK INSERT),但第二个过程需要大约30分钟才能执行。流程2中的“问题”SQL如下:

INSERT INTO ProductionTable(field1,field2)
SELECT field1, field2
FROM SourceHeapTable (nolock)

上面的INSERT语句将数十万条记录插入到ProductionTable中,每行分配一个UNIQUEIDENTIFIER,并插入大约5个不同的索引。我很欣赏这个过程需要很长时间,所以我的问题是:当导入正在进行时,第三个进程负责在ProductionTable上执行常量查找 - 除了在表中插入一条额外的记录:

INSERT INTO ProductionTable(fields...)
VALUES(values...)

SELECT *
FROM ProductionTable (nolock)
WHERE ID = @Id

对于上面INSERT...SELECT发生的大约30分钟,INSERT INTO次超时。

我的想法是SQL服务器在INSERT...SELECT期间锁定整个表。在我的分析过程中,我在服务器上进行了大量的分析,并且在INSERT...SELECT的持续时间内肯定会分配锁,但我记不清它们的类型。

从来没有需要同时从两个来源的表中插入记录 - 至少在ETL过程中 - 我不知道如何处理这个问题。我一直在查找INSERT表提示,但大多数在将来的版本中已经过时了。

在我看来,CURSOR是唯一能够到达这里的方式吗?

2 个答案:

答案 0 :(得分:2)

您可以考虑将BULK INSERT用于Process-2以将数据导入ProductionTable。

另一个选择是将Process-2批量处理成大约1000个记录的小批量,并使用表值参数来执行INSERT。请参阅:http://msdn.microsoft.com/en-us/library/bb510489.aspx#BulkInsert

答案 1 :(得分:0)

好像是桌子锁。

尝试在ETL过程中插入部分。像

这样的东西
while 1=1
begin

   INSERT INTO ProductionTable(field1,field2)
   SELECT top (1000) field1, field2
   FROM SourceHeapTable sht (nolock)
   where not exists (select 1 from ProductionTable pt where pt.id = sht.id)

   -- optional
   --waitfor delay '00:00:01.0'

   if @@rowcount = 0 
      break;

end