跨链接服务器的远程查询的SQL性能问题


8

这个过程

create proc dbo.Get_Accounts as
begin
  declare @current_date datetime
  set @current_date = dbo.fn_currdate()

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = @current_date
end

10分钟后连续失败,并显示以下错误消息:

服务器:消息7399,级别16,状态1,行1 OLE DB提供程序'SQLOLEDB'报告了错误。提供程序终止了执行,因为达到了资源限制。[OLE / DB提供程序返回的消息:超时已过期] OLE DB错误跟踪[OLE / DB提供程序'SQLOLEDB'ICommandText :: Execute返回0x80040e31:执行程序由于达到资源限制而被执行程序终止。

但是,当我在具有硬编码日期的交互式查询窗口中从同一数据库(不在远程数据库)中运行同一查询时:

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = '1/20/2012'

30秒后返回。

本地服务器是SQLSERVER 2008,远程服务器是SQLSERVER 2000。

我们做了以下工作无济于事:

  • 重新创建存储的过程。
  • sp_recompile对存储的proc
  • 更新dbo.accounts上的统计信息
  • 删除并重新创建dbo.accounts上的索引
  • 删除dbo.accounts上的索引并尝试
  • 本地和远程服务器上的DBCC FREEPROCCACHE和DBCC DROPCLEANBUFFERS
  • 重新启动远程服务器(在本地服务器上不是一个简单的选择)

问题

  • 谁能解释这种奇怪的行为?
  • 关于其他更正的选择有什么建议吗?

Answers:


11

您可以打开跟踪标志7300,这可能会给您更详细的错误消息

代表性查询返回多少行?两台服务器之间的网络连接速度/可靠性如何?

大型数据集传输所需的时间可能太长(在实际查询时间之上)。您可以提高超时值。

您可以尝试重新配置超时设置,如下所示:

将远程登录超时设置为300秒:

sp_configure 'remote login timeout', 300
go 
reconfigure with override 
go 

将远程查询超时设置为0(无限等待):

sp_configure 'remote query timeout', 0 
go 
reconfigure with override 
go 

更新:从SQL Server 2012 SP1开始:具有SELECT权限的用户将能够访问DBCC SHOW_STATISTICS,这将改善链接服务器上的只读性能。参考:https : //msdn.microsoft.com/zh-cn/library/ms174384(v= sql.110) .aspx

更新:您说的不是数据的大小或连接速度是正确的。它在我迷雾的记忆中敲响了钟声,我想起了在哪里看到的:应用程序中的速度慢,SSMS中的速度快?(链接服务器的问题)。这不是参数嗅探,而是缺少统计信息本身(由于权限),导致使用了错误的查询计划:

您可以看到估计是不同的。当我以sysadmin身份运行时,估计为1行,这是正确的数字,因为Northwind中没有订单ID超过20000的Orders。但是当我以普通用户身份运行时,估计为249行。我们将该特定数字识别为830个订单中的30%,或者当优化器没有信息时对不等式操作的估计。以前,这是由于未知的变量值引起的,但是在这种情况下,没有任何未知的变量。不,缺少统计信息本身。

只要查询只访问本地服务器中的表,优化器就可以始终访问查询中所有表的统计信息;没有额外的权限检查。但这与链接服务器上的表不同。当SQL Server访问链接的服务器时,没有秘密协议仅用于服务器间的通信。不,相反,SQL Server使用标准的OLE DB接口来链接服务器,可以是其他SQL Server实例,Oracle,文本文件或自酿数据源,并且可以像任何其他用户一样进行连接。究竟如何检索统计信息取决于数据源和相关的OLE DB提供程序。在这种情况下,提供程序是SQL Server Native Client,它分两步检索统计信息。(您可以通过对远程服务器运行Profiler来看到此信息)。首先,提供程序运行sp_table_statistics2_rowset过程,该过程返回有关存在哪些列统计信息以及其基数和密度信息的信息。在第二步中,提供程序运行DBCC SHOW_STATISTICS,该命令返回完整的分发统计信息。(我们将在本文后面的部分中仔细研究此命令。)这是要抓住的地方:要运行DBCC SHOW_STATISTICS,您必须是服务器角色sysadmin或任何数据库角色db_owner或db_ddladmin的成员。

这就是为什么我得到不同结果的原因。当以sysadmin身份运行时,我得到了完整的分发统计信息,该统计信息表明没有订单ID> 20000的行,估计为一行。(回想一下,优化器永远不会从统计信息中假设零行。)但是,当以普通用户身份运行时,DBCC SHOW_STATISTICS失败,并出现权限错误。不会传播此错误,但是优化程序会接受没有统计信息并使用默认假设。由于它确实获得了基数信息,因此了解到远程表有830行,据此估计有249行。

每当遇到性能问题,其中包含对链接服务器的访问的查询在应用程序中运行缓慢,但从SSMS测试该查询时运行速度很快,则应始终调查是否可能导致对远程数据库的权限不足。(请记住,对链接服务器的访问可能不会在查询中公开,但可能会隐藏在视图中。)如果确定问题出在远程数据库上,那么您可以采取什么措施?

  • 您可以将用户添加到db_ddladmin角色,但是由于这使他们有权添加和删除表,因此不建议这样做。

  • 默认情况下,当用户连接到远程服务器时,他们将自己连接,但您可以使用sp_addlinkedsrvlogin设置登录映射,以便用户映射到在db_ddladmin中具有成员身份的代理帐户。请注意,此代理帐户必须是SQL登录名,因此,如果远程服务器未启用SQL身份验证,则不能选择此选项。从安全角度来看,此解决方案也有些可疑,尽管它比以前的建议要好。

  • 在某些情况下,您可以使用OPENQUERY重写查询以强制在远程服务器上进行评估。如果查询包含多个远程表,这将特别有用。(但是它也会适得其反,因为优化器现在从远程服务器获取的统计信息甚至更少。)

  • 您当然可以使用全部的提示和计划指南来获取所需的计划。

  • 最后,您应该问自己是否需要链接服务器访问。也许数据库可以在同一台服务器上?可以复制数据吗?其他解决方案?


它返回大约14万条记录。但是由于当日期值被硬编码时它工作得很好,所以我想不出会极大地影响参数化版本的I / O或网络问题。我的直觉说,查询正在传递到远程服务器,并且远程优化器在无法理解参数时以某种方式选择了错误的查询计划。但是重新索引和清除高速缓存/缓冲区应该纠正这一点(我认为)。我将研究超时,看看是否至少可以使它返回。谢谢

1
很好的答案,并准确解释了我遇到的问题,谢谢。我还要补充说,根据MSDN,从SQL2012 SP1开始,具有SELECT权限的用户将能够访问DBCC SHOW_STATISTICS,这将改善链接服务器上的只读性能,而不必牺牲安全性。
史蒂夫·佩蒂弗

2

尝试此操作(即明确指示应在远程服务器上运行的内容)时会发生什么?

select [fields]
into dbo.current_accounts
from OPENQUERY(linkedserver, 'SELECT [fields] FROM database.dbo.accounts where date = ''1/20/2012''');

我怀疑在您上面的情况下,SQL Server只是从远程服务器提取整个表,然后在本地运行查询(我已经看到这种情况在过去多次发生过)。我更喜欢露骨(通过使用OPENQUERY或在远程服务器上创建SP),因此不会造成混乱。


1

由于这是一个资源问题,因此SQL Server外部的内存池用于加载外部驱动程序和CLR可能已接近其限制。默认值为256MB。为了解决这个问题,我建议您转到SQL Server配置管理器的“高级”选项卡,然后在启动参数的末尾添加-g选项。即-g1024,然后重新启动SQL Server服务。我通常这样做,因为我们使用了大量的链接服务器。 http://msdn.microsoft.com/en-us/library/ms190737.aspx


1

我有两个想法可能会有所帮助。我还要告诉您,在链接服务器上运行查询的性能使我感到倒霉。所以我的第一个建议是,如果可以的话,请避免使用它。

我的第一个想法是将存储过程安装到SQL Server 2000框中,并使其引用本地服务器。然后,您可以远程执行存储过程。

exec linkedserver.database.dbo.Get_Accounts

如果您能走这条路,它将极大地提高性能。

我的第二个想法是在运行存储过程时获得估计的查询计划。它向您显示花费了很多时间吗?一个潜在的问题是,您在链接服务器上使用的帐户可能没有足够的权限来获取表统计信息(链接服务器比本地服务器需要更多的权限)。这会使查询变得异常缓慢。您可以在此处阅读有关该特定问题的更多信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.