在工作中我们有两台服务器,一台运行一个很多人使用的应用程序,它有一个SQL Server 2000后端。我可以自由地查询这个很长一段时间但不能添加任何东西,如存储过程或额外的表。
这导致我们将第二个SQL Server链接到第一个SQL Server,然后构建一个存储过程库,使用链接服务器从双方查询数据。其中一些查询花费的时间比我想要的要长。
有人能指点我一些关于使用链接服务器的好文章吗?我特别感兴趣的是找出两者之间正在传输的数据,因为通常大多数sql语句都可以远程执行,但我感觉它可能正在转移整个表,它通常只是一个小的最终的连接本地表。
此外,我目前拥有的链接服务器选项是什么:
修改
我想我会更新这篇文章,我使用动态参数的openqueries一段时间来提升性能,感谢提示。但是,当你最终处理字符串时,这样做可能会使查询更加混乱。最后,今年夏天我们将SQL Server升级到2008并实现了实时数据镜像。说实话,开放查询接近我的任务的本地查询的速度,但镜像肯定使sql更容易处理。
答案 0 :(得分:8)
避免加入链接服务器表。
可以使用连接的四部分命名,但更昂贵。您的联接可以包含可用于限制链接服务器中的数据集并使用索引列的条件。
示例:
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(或任何链接的服务器)放在循环中!
答案 1 :(得分:3)
当您使用链接服务器进行这样的连接时,让您立即连接的服务器(“本地”)成为具有最多数据的服务器非常重要,其中链接服务器仅提供一小部分数据,否则,是的,它将提取执行连接所需的数据。
备选方案包括将数据的子集复制到临时表,同时完成尽可能多的工作以减少结果和链接服务器可以执行的任何预处理,然后在“本地”端进行连接。
您可能会发现通过颠倒您的方式,连接到您无法控制的服务器(他们需要为您创建链接服务器),然后通过链接连接到您的服务器,您可以轻松提升性能。如果您需要对必须创建sprocs的数据进行主要工作 - 然后将数据推送到服务器并在那里使用您的sprocs。
在某些情况下,我只是让链接服务器执行这种摘要的夜间创建,然后将其推送到本地服务器,然后本地服务器通过连接执行其工作。
答案 2 :(得分:3)
皇家痛苦
我们以前在我们的商店有几个链接的服务器,结果是这样的PITA 。
首先,存在类似于您描述的严重性能问题。当我看到网络I / O统计数据时,我感到很震惊。尽管付出了很多努力,但我们未能提示SQL Server采取合理的行为。
另一个问题是存储过程在任何地方都有硬编码的这些链接服务器名称,无法覆盖它们。因此,开发人员无法轻松地在其开发沙箱中测试任何触及链接服务器的功能。这是创建一个通用的单元测试套件的主要障碍。
最后,我们完全抛弃了链接服务器,并将数据同步转移到了Web服务。
答案 3 :(得分:2)
跨链接服务器涉及半连接的查询往往效率不高。您可能最好使用OPENQUERY将数据填充到本地临时表中,然后从那里开始处理。
答案 4 :(得分:1)
几年前我在SQL 2000中编写了一个远程链接服务器应用程序,遇到了您描述的相同性能问题。为了获得最佳性能,我最终重写了几次我的存储过程。
我广泛使用临时表。我发现将大量远程数据检索到临时表,然后加入它,操纵它等等,这样做的成本更低。加入本地到远程表的速度非常慢。
显示执行计划和显示预计执行计划往往有所帮助,虽然我不了解我所看到的很多内容。
我不知道是否确实有一种有效的方法来使用远程服务器进行这些查询,因为看起来SQL Server在针对链接服务器时无法利用其常规优化。您可能觉得自己正在转移整个表格,因为实际情况就是这样。
我想知道复制方案是否适合您。通过在本地服务器上提供数据,您应该能够编写将按预期执行的普通查询。
我不知道有什么好文章可以指向你。当我编写更复杂的SQL Server应用程序时,我开始认为我需要更好地理解SQL Server如何在其下工作。为此,我们在工作中购买了由Kalen Delaney编辑的MS Press Inside Microsoft SQL Server 2005系列。第1卷:存储引擎绝对是开始的地方,但我还没有那么深入。由于我的最后几个项目没有涉及SQL Server,我对它的研究已经松懈。
答案 5 :(得分:0)
是否有可能在服务器上设置单独的数据库而不是使用链接服务器?
答案 6 :(得分:0)
我建议在游标循环中使用动态openqueries而不是链接连接。
这是我能够复制MS Access'链接连接性能的唯一方法(至少对于单个远程表)。
ms sql中的常规链接连接通过在特别强大的表中提取所有内容来实现效率太低..
- 我想知道游标循环中的openqueries有什么坏处?如果操作正确,则没有锁定问题。
答案 7 :(得分:0)
这是一个非常慷慨的问题,可能有很多解决方案。但是,正如我们目睹了这么多用户说他们已经尝试了一切。
解决了我的问题是......
我将sql server 2000从sp2升级到SP4,如果你已经在sql server 2000上安装了sp4,那么运行Instcat.sql。根据我的经验,我可以向你保证,如果你对所有其他的解决方法都感到筋疲力尽,这肯定会有用。
谢谢, Mithalesh mithalesh.gupta@gmail.com
答案 8 :(得分:0)
动态SQL和函数可用于解决硬编码的名称问题。例如,我正在尝试一个实现,其中函数ufn_linkedDatabase(@purpose nvarchar(255))输入'cpi.cpi'(目的CPI,子目的默认值)返回 '[SERVER-NAME.DOMAIN.LCL,2000]。[CPI]'在生产环境中(我们使用SQL Server的备用端口号,我不知道为什么,包括链接服务器名称)。然后在@template varchar(max)中汇编SQL命令,表达式@ {cpi.cpi}表示链接服务器和数据库,然后 @workstring = REPLACE(@template,N'@ {cpi.cpi}',...)。函数实际获取数据库名称的方式与过程是分开的 - 查找表很好。
问题 - 要做OPENQUERY(),这可能仍然更好,至少除非链接服务器选项“collation compatible”设置为“true”,以便可以在链接服务器上执行更多任务 - 即使在快速网络,我们的服务器机房内部网络速度相当快 - 做OPENQUERY()我可能需要分别处理'cpi.cpi.server'和'cpi.cpi.database'和'cpi.cpi.server.database'。而且,我最终可能会使用这种设计编写一个应用程序,在这种情况下它是过度设计的。尽管如此,这意味着该功能本身并不一定是任何花哨的工作。
无论如何,在问题上投掷快速网络硬件可能是更便宜的答案。