在上一遍文章中介绍了SQLServer通过链接服务器访问Oracle性能问题的解决方法,本文介绍链接服务器下远程删除SQLServer数据的性能问题解决 1. 问题发现 系统中有个功能,需要远程删除SQLServer实例的表数据,删除语句中有where条件,条件中有一个子查询。 该
在上一遍文章中介绍了SQLServer通过链接服务器访问Oracle性能问题的解决方法,本文介绍链接服务器下远程删除SQLServer数据的性能问题解决
系统中有个功能,需要远程删除SQLServer实例的表数据,删除语句中有where条件,条件中有一个子查询。
该功能前台执行速度非常慢。所以准备调优。
下面为演示代码,未优化前如下:
<span><span>DELETE</span> <span>FROM</span> <span>[</span><span>LINKSERVERNAME</span><span>]</span>.<span>[</span><span>AdventureWorks2008</span><span>]</span>.<span>[</span><span>Sales</span><span>]</span>.<span>[</span><span>SalesOrderDetail</span><span>]</span> <span>WHERE</span> SalesOrderDetailID<span>=</span><span>5</span> <span>AND</span> <span>EXISTS</span>(<span>SELECT</span> <span>TOP</span> <span>1</span> <span>1</span> <span>FROM</span> <span>[</span><span>LINKSERVERNAME</span><span>]</span>.<span>[</span><span>AdventureWorks2008</span><span>]</span>.<span>[</span><span>Sales</span><span>]</span>.<span>[</span><span>SalesOrderDetail</span><span>]</span>)</span>
此时的执行计划如下图:
可以看到执行计划存在一个远程扫描,然后在本地执行筛选。
在远程服务器开启profiler跟踪,部分内容如下图:
可以看到远程服务器开启了一个游标,然后逐行读取数据并返回给调用端。
可以预见性能会非常差,如何避免不带where条件的远程扫描呢?
使用OpenQuery将delete数据的筛选提交到远程服务器执行。
<span><span>DELETE</span> <span>FROM</span> <span>OPENQUERY</span>(<span>[</span><span>LINKSERVERNAME</span><span>]</span><span> ,</span><span>'</span><span>SELECT * FROM [AdventureWorks2008].[Sales].[SalesOrderDetail] WHERE SalesOrderDetailID=5 AND EXISTS(SELECT TOP 1 1 FROM [AdventureWorks2008].[Sales].[SalesOrderDetail])</span><span>'</span><span> )</span></span>
此时,执行计划如图:
将整个delete语句提交到远程执行
<span><span>DECLARE</span> <span>@sql</span> <span>nvarchar</span>(<span>max</span><span>) </span><span>SELECT</span> <span>@sql</span> <span>=</span><span>'</span><span> DELETE FROM [AdventureWorks2008].[Sales].[SalesOrderDetail] WHERE SalesOrderDetailID=5 AND EXISTS(SELECT TOP 1 1 FROM [AdventureWorks2008].[Sales].[SalesOrderDetail]) </span><span>'</span> <span>exec</span> <span>[LINKSERVERNAME</span><span>]</span>.<span>[</span><span>AdventureWorks2008</span><span>]</span>.dbo.sp_executesql <span>@sql</span></span>
profiler跟踪到的语句如下:
如有不对的地方,欢迎拍砖;如有其他方法,求分享,谢谢!