在工作中,我们有两台服务器,其中一台正在运行很多人使用的应用程序,该应用程序具有 SQL Server 2000 后端。我很长时间以来都可以自由地查询它,但无法向其中添加任何内容,例如存储过程或额外的表。

这导致我们将第二个 SQL Server 链接到第一个 SQL Server,并且我构建了一个存储过程库,使用链接服务器从双方查询数据。其中一些查询花费的时间比我想要的要长。

有人可以给我指出一些关于使用链接服务器的好文章吗?我特别感兴趣的是找出两者之间正在传输哪些数据,因为通常大多数 sql 语句都可以远程执行,但我感觉它可能正在传输整个表,它通常只是一个小型最终的连接本地表。

另外,我目前有哪些链接服务器选项:

  • 排序规则兼容 True
  • 数据访问真实
  • 远程调用真实
  • Rpc 输出正确
  • 使用远程排序规则 False
  • 排序规则名称(空白)
  • 连接超时 0
  • 查询超时 0

编辑:

只是想我会更新这篇文章,我使用带有动态参数的 openqueries 一段时间来提高性能,感谢您的提示。然而,当您最终处理字符串时,这样做可能会使查询变得更加混乱。最终今年夏天我们将SQL Server升级到2008并实现了实时数据镜像。老实说,对于我的任务来说,开放查询的速度已经接近本地查询的速度,但镜像确实使 SQL 更容易处理。

有帮助吗?

解决方案

我建议在游标循环中使用动态开放查询而不是链接连接。这是我能够复制 MS Access 链接联接性能的唯一方法(至少对于单个远程表而言)

MS sql 中的常规链接联接通过将所有内容专门拉入巨大的表中而效率太低。

-- 我想知道游标循环内的 openqueries 有什么不好?如果操作正确,就不存在锁定问题。

其他提示

避免连接到链接服务器表。

可以使用四部分命名来进行连接,但成本更高。您的联接可以包含可用于限制来自链接服务器的数据集并使用索引列的条件。

例子:

SELECT loc.field1, lnk.field1
FROM MyTable loc
INNER JOIN RemoteServer.Database.Schema.SomeTable lnk
  ON loc.id = lnk.id
  AND lnk.RecordDate = GETDATE()
WHERE loc.SalesDate = GETDATE()

该查询还在连接中应用了链接服务器在计算连接之前可以使用的条件。

推荐的方法是使用 OPENQUERY。

通过使用 OPENQUERY 避免连接,本地服务器仅发送要远程执行的查询,而不是发送用于连接的一组 ID。

使用该链接检索一组数据并在本地执行计算。使用临时表(用于即席查询)或在夜间作业中将行插入永久表中。

开始事务可能会失败,具体取决于喜欢的服务器中是否设置了远程事务协调器。使用它会消耗更多的资源。

还要考虑到您正在访问运行应用程序的生产服务器,虽然您没有指定它,但我认为可以安全地假设正在使用大量事务并执行插入和更新。您正在从应用程序中夺走资源。

您的目的似乎是将数据用于报告目的。您的服务器可以设置为具有简单的日志而不是完整的日志,从而提高效率。

您还可以避免由于链接服务器上的数据移动而取消查询。请始终注意为查询和表提示(例如 NOLOCK)设置适当的隔离级别。

还有请!切勿将 OPENQUERY(或任何链接服务器)放置在循环内!

当您使用链接服务器进行此类联接时,重要的是让您立即连接到的服务器(“本地”)成为拥有最多数据的服务器,而链接服务器仅提供一小部分数据,否则,是的,它将提取执行连接所需的尽可能多的数据。

替代方案包括将数据子集复制到临时表,并完成尽可能多的工作以精简结果以及链接服务器可以执行的任何预处理,然后在“本地”端进行联接。

您可能会发现,通过反转操作方式,连接到您无法控制的服务器(他们需要为您创建链接服务器),然后通过链接连接到您的服务器,您可以轻松提高性能。如果您需要对必须创建存储过程的数据进行主要工作 - 则将数据推送到您的服务器并在那里使用您的存储过程。

在某些情况下,我只是让链接服务器每晚执行一次此类摘要的创建,并将其推送到本地服务器,然后本地服务器通过连接执行其工作。

皇家痛苦

我们的商店曾经有几个链接服务器,结果是 这样的皮塔饼.

首先,存在与您描述的类似的严重性能问题。当我看到网络 I/O 统计数据时,我感到震惊。尽管付出了一切努力,我们还是未能提示 SQL Server 采取合理的行为。

另一个问题是存储过程将这些链接服务器名称硬编码到各处,无法覆盖它们。因此,开发人员无法轻松地在其开发沙箱上测试任何涉及链接服务器的功能。这是创建通用的单元测试套件的主要障碍。

最后,我们完全放弃了链接服务器,并将数据同步转移到网络服务。

涉及跨链接服务器半连接的查询往往效率不高。你可能最好使用 开放查询 将数据填充到本地临时表中,然后从那里对其进行处理。

几年前,我用 SQL 2000 编写了一个远程链接服务器应用程序,并遇到了您所描述的相同性能问题。为了获得最佳性能,我最终多次重写了存储过程。

我广泛使用临时表。我发现将大量远程数据检索到临时表中,然后连接到它、操作它等的成本较低。正如您所描述的,将本地表连接到远程表非常慢。

尽管我不明白我所看到的很多内容,但显示执行计划和显示估计执行计划往往会有所帮助。

我不知道是否真的有一种有效的方法来使用远程服务器执行这些查询,因为在对抗链接服务器时,SQL Server 似乎无法利用其正常的优化。可能感觉您正在转移整个表,因为事实上这就是正在发生的情况。

我想知道复制方案是否适合您。通过将数据存储在本地服务器上,您应该能够编写将按需要执行的正常查询。

我不知道有什么好的文章可以向您指出。当我编写更复杂的 SQL Server 应用程序时,我开始认为我需要更好地了解 SQL Server 底层的工作原理。为此,我们购买了由 Kalen Delaney 编辑的 MS Press Inside Microsoft SQL Server 2005 系列。第一卷:存储引擎绝对是一个起点,但我还没有深入研究它。由于我最近的几个项目都没有涉及到SQL Server,所以对它的研究就比较松懈了。

您是否可以在服务器上设置单独的数据库而不是使用链接服务器?

这是一个非常慷慨的问题,可能有很多解决方案。但正如我们目睹的许多用户说他们已经尝试了一切。

解决我的问题的是..

我将 sql server 2000 从 sp2 升级到 SP4,如果 sql server 2000 上已经有 sp4,则运行 Instcat.sql。根据我的经验,如果您对所有其他解决方法感到疲惫不堪,我可以向您保证,这肯定会起作用。

谢谢,mithalesh mithalesh.gupta@gmail.com

动态 SQL 和函数可用于解决硬编码名称问题。例如,我正在尝试使用输入'cpi.cpi'(目的cpi,sub-purpose默认值)返回'[server-name.domain.lcl,2000]的函数ufn_linkeddatabase(@purpose nvarchar(255))函数ufn_linkedDatabase(@purpose nvarchar(255))。 [CPI]在生产环境中(我们在其中使用SQL Server的替代端口号,我不知道为什么,包括链接服务器名称中)。然后将SQL命令与表示链接服务器和数据库的express @{cpi.cpi}在@template varchar(max)中组装在一起,然后@workString = repleast(@template,n'@ {cpi.cpi}',。 ..)。该函数如何实际获取数据库名称与过程是分开的 - 查找表很好。

问题 - 执行 OPENQUERY(),至少除非将链接服务器选项“排序规则兼容”设置为“true”,以便可以在链接服务器上执行更多任务 - 即使在快速网络上也很重要,我们的服务器机房内部网络速度相当快 - 要执行 OPENQUERY() 我可能需要分别处理“cpi.cpi.server”和“cpi.cpi.database”和“cpi.cpi.server.database”。而且,我最终可能会使用这种设计编写一个应用程序,在这种情况下,它就被过度设计了。不过,这意味着该函数本身不必是任何花哨的工作。

无论如何,使用快速网络硬件来解决问题可能是更便宜的答案。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top