我目前正在客户端的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
是唯一能够到达这里的方式吗?
答案 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