我到处寻找这种情况,但找不到解决方案除了动态 SQL,我不想使用它.
这是我想要在服务器 2 上更新的表:
(Stuff Id UNIQUEIDENTIFIER
, stuffname NVARCHAR(64))
我需要从服务器 1 更新它。
所以我一直在尝试这样做:
DECLARE @newstuff nvarchar(64)
SELECT @newstuff = 'new stuff'
UPDATE [server2].database2.dbo.Stuff
SET stuffname=@newstuff
WHERE stuffId='4893CD93-08B3-4981-851B-5DC972288290'
这需要 11 秒。下一个使用文字的运行时间不到 1 秒
UPDATE [server2].database2.dbo.Stuff
SET stuffname='new stuff'
WHERE stuffId='4893CD93-08B3-4981-851B-5DC972288290'
我对比了实际的执行计划。慢的是进行远程扫描,需要 100% 的成本,再加上 5 个其他步骤(过滤器、表假脱机、计算标量、远程更新、更新)。快速的只执行更新和远程查询步骤。我需要使用变量,所以我需要一种方法来强制它远程执行整个查询。
我尝试过使用 OPTION(RECOMPILE),但 server1 使用的是 SQL Server 2005。server2 使用的是 SQL Server 2012。如果没有严重问题,我根本无法更改 server2 上的数据库结构。我没有任何身份验证问题。我在更新表时尝试给表添加别名。
我也尝试过使用 Openquery。当我将 id 过滤器放入查询字符串中时,它会恢复到 1 秒以下:
UPDATE OPENQUERY([server2], 'select stuffname, stuffid from database2.dbo.stufftable where contactid=''4CA1D489-9221-E511-A441-005056C00008''')
SET stuffname = @newstuff
但我也需要该 id 成为一个变量,并且该开放查询不接受变量(https://msdn.microsoft.com/en-CA/library/ms188427.aspx https://msdn.microsoft.com/en-CA/library/ms188427.aspx)。我尝试在查询之外使用 id 过滤器运行 Openquery,但运行时间为 4 秒。它比 11 好,但还不是很好:
UPDATE OPENQUERY([server2],'select stuffname, stuffid from database2.dbo.stufftable')
set stuffname=@newstuff
where contactid='4CA1D489-9221-E511-A441-005056C00008'
当然,我使用 exec(@sql) 运行 openquery,但我真的不想那样做。我可以使用文字以这种方式执行整个更新语句,甚至不使用 OPENQUERY 并获得相同类型的结果。
有什么方法可以让我在不使用 exec(@sql) 的情况下修复此性能?