【问题标题】:tsql - joining two tables from different databases hosted on separate serverstsql - 连接来自不同服务器上托管的不同数据库的两个表
【发布时间】:2014-11-25 01:50:45
【问题描述】:

我有 2 个数据库位于不同的物理服务器上并已链接。我需要将 DB1.T1 与 DB2.T2 连接起来并创建一个 ID。问题是性能。我的学长坚持使用一个函数,我在下面创建了它。

IF OBJECT_ID (N'dbo.getXXXId', N'FN') IS NOT NULL
    DROP FUNCTION dbo.getTRId;
GO
CREATE FUNCTION dbo.getTRId (@gcPRef bigint)
RETURNS varchar (100)
WITH EXECUTE AS CALLER --may not be necessary. not sure.
AS
BEGIN

     DECLARE @TRID varchar (100);
     SELECT @TRID =  CONVERT(varchar (12), hu2.PropId) 
              + '_'+ CONVERT(varchar (12), c.WSId)
        FROM [172.29.110.133].DB1.dbo.checks c
        join [172.29.110.133].DB1.[dbo].VHier
                          ON VHier.xx= c.xx
        join [172.29.110.133].DB1.[dbo].rvc
                          ON rvc.xx= VHier.xx
                          AND rvc.yy= VHier.yy
        join [172.29.110.133].DB1.[dbo].HUNIT hu
                          ON c.xx= hu.xx
    WHERE c.CheckId = @gcPRef;

     RETURN (@TRID);
END;
GO

我使用下面的查询来使用上面的函数查询每个 checkid。

select getTRId(guestCheckPRef), guestCheckid from DB2.Guest_CHECKS GC
where GC.closeBusinessDate = '2014-06-25'

您可能想知道的几件事:

  • DB1 和 DB2 托管在不同的物理服务器上。
  • 我不是 DBA,所以如果我做错了什么,请告诉我。
  • 每天创建大约 45000 条记录。所以这是行数..
  • 我已经尝试在不涉及函数的情况下加入它们。它需要永远。在 30 秒内,仅返回 450 条记录。我不能长时间锁定表格。
  • CONSTRAINT [DB1.PK_CHECK] 主键集群
  • CONSTRAINT [DB2.XPKGUEST_CHECKS] 主键非集群
  • 我不知道约束是否在这里起作用。 DB2.GUEST_CHECKS.guestCheckPRef 在这里甚至不是 FK。 guestCheckPRef 是 DB1.CHECK 中的 PK。
  • 性能很差。我需要返回 DB2.propid + DB2.wsid + DB1.guestCheckid。

这是我目前所能提供的。任何建议表示赞赏。不一定要用函数来完成。

提前致谢。问候。奥兹。

【问题讨论】:

  • 您是否尝试过在 DB1 本身中拥有此功能?因为您的函数不使用任何 DB2 表。只需在本地数据库中拥有该功能并从其他数据库调用它。
  • 链接服务器几乎总是会破坏您的性能。无论您的查询的其余部分如何调整,链接服务器都会杀死您。另外,你为什么把它作为一个函数而不是一个存储过程来做?
  • @NMK。谢谢你。也许我没有说清楚。该函数存储在 DB2 上,远程访问 DB1。是的,我已将该函数存储在 DB1 上,并尝试从 DB2 远程访问它,但未成功,因为消息来源说您无法远程调用函数。此外,我们的客户将使用它,他们只能访问 DB2.Regards.Oz。
  • @alroc。您对链接服务器非常正确。我有一个本地数据库有 10000 个数据,使用这种方法只需几秒钟即可检索相同数量的数据。这是一个结构良好的数据库。但是这个请求非常不寻常,来自一个客户。所以我只是拼命寻找解决方案。我已经以不同的方式开发了它,但无法满足它们。顺便说一句,我没有看到 SP 和功能之间的任何性能差异。我会尝试一下,只是为了有个想法。谢谢!。

标签: sql-server tsql


【解决方案1】:

以下是一些可以尝试或考虑的事情:

  1. 您是否检查过查询是否使用了最佳可用索引?您可以尝试通过查询分析器运行查询,看看是否可以添加任何索引来提高性能。

  2. 您运行的是什么版本的 SQL Server?根据版本,您可能能够将表从一台服务器复制到另一台服务器,以降低在网络中运行查询的成本。

  3. 我注意到有几个连接跨到另一台服务器 - 您能否将所有这些连接合并到使用索引优化的单个视图中 - 可能会导致网络流量减少。

    李>
  4. 尝试将您的函数放在另一台服务器上并从第一台服务器调用它,看看是否有任何性能改进。

【讨论】:

  • 我认为这里的 #4 将是最好的选择,无需在服务器之间复制数据。
【解决方案2】:

在函数中执行“选择”通常被认为“不是一个好主意”。函数中的选择会对结果集中的每一行重复一次,这可能是性能不好的原因。

呃。这应该是评论,而不是答案。要将其转换为正确的答案,请将查询重写为联接,而不使用该函数。 (即获取函数的内容并将其集成到单个连接中。)

您的示例查询应如下所示:

;with getTRID as 
(SELECT CONVERT(varchar (12), hu2.PropId) 
  + '_'+ CONVERT(varchar (12), c.WSId) AS TRID
  FROM [172.29.110.133].DB1.dbo.checks c
join [172.29.110.133].DB1.[dbo].VHier
  ON VHier.xx= c.xx
join [172.29.110.133].DB1.[dbo].rvc
  ON rvc.xx= VHier.xx
  AND rvc.yy= VHier.yy
join [172.29.110.133].DB1.[dbo].HUNIT hu
  ON c.xx= hu.xx)
select getTRId.TRID, guestCheckid from DB2.Guest_CHECKS GC
inner join getTRID ON CheckId = guestCheckPRef
where GC.closeBusinessDate = '2014-06-25'

注意我在这里从记忆中工作,所以请不要因为语法错误而起火!谢谢。

史蒂夫·G。

【讨论】:

  • 感谢您的回复和时间。我已经尝试过这个并修复了语法并不是什么大问题。它也是资源密集型的。甚至返回 100 条记录都需要花费很多时间。我相信这是一个网络/链接服务器问题。
  • 如果时间真的是最重要的,另一个建议是在进行任何连接之前,将所有远程服务器的有问题的数据缓存在“本地”服务器上。我将首先将相关数据选择到每个服务器上的临时表中,然后通过网络复制临时数据表。这应该使您对源表的影响最小,还有助于减少网络延迟的影响。
猜你喜欢
  • 2012-06-22
  • 2012-10-23
  • 2014-10-05
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
相关资源
最近更新 更多