我在存储过程中遇到了一个问题,它将数据从一个表递增复制到另一个表:
DECLARE @StartId bigint;
SELECT @StartId = COALESCE(MAX(Id), 0)
FROM dbo.TargetTable WITH (NOLOCK);
INSERT INTO dbo.TargetTable (...)
SELECT ...
FROM dbo.SourceTable
WHERE Id > @StartId
这个存储过程被绞死超过15分钟,我将其杀死。但是,如果我分开运行这两个部分,
SELECT COALESCE(MAX(Id), 0)
FROM dbo.TargetTable WITH (NOLOCK);
它会立即返回头部ID,例如100000。
然后我在@StartId
语句中将INSERT
变量替换为100000并运行它,
INSERT INTO dbo.TargetTable (...)
SELECT ...
FROM dbo.SourceTable
WHERE Id > 100000
此部分在不到几秒钟内完成。
似乎在原始存储过程中,变量@StartId
被内联到INSERT
语句中,从而导致死锁。
我知道可能有更好的方法或解决方法,例如将进度存储在第三个表中,但是,我的问题是我可以在输入INSERT
语句之前强制对变量进行评估吗?
编辑:由于这是在存储过程中,我没有选择使用GO。
答案 0 :(得分:1)
我刚刚发现原因并非内联变量表达式,而是涉及变量的执行计划问题。
已经有了Q / A,应用OPTION(RECOMPILE)
的答案对我很有用:
答案 1 :(得分:-2)
这可能看起来很直接,但你可以把它们放在两个不同的交易中......所以首先你要做你的
BEGIN TRANSACTION GetMax
SELECT COALESCE(MAX(Id), 0) FROM dbo.TargetTable WITH (NOLOCK);
GO
INSERT INTO dbo.TargetTable (...)
SELECT ...
FROM dbo.SourceTable
WHERE Id > 100000
GO
COMMIT TRANSACTION GetMax;
GO
你能试试吗?