SQL SERVER - 链接服务器和查询性能

ced*_*ced 7 performance sql-server view linked-server query-performance

我有一个与 SQL Server/链接服务器/视图相关的性能问题。我希望你能帮助我理解什么是做我想做的最好的方法 =)。

  • 我有一个数据库 K,其中包含 3 个链接服务器 L1、L2、L3 到 3 个数据库 X、Y、Z。
  • 在 X、Y、Z 中,我分别有 3 个视图,称为 V1、V2、V3。
  • 我想通过数据库 K 与链接服务器 L1、L2、L3 查询 V1、V2、V3 的并集。

经过一些测试,情况是这样的:

  1. 在 SSMS 中,如果我运行这个伪查询SELECT * FROM (L1.V1 u L2.V2 u L3.V3) WHERE some filters,性能真的很棒
  2. 如果我在数据库 K 中创建一个视图 VK,其中包含三个视图的并集,然后我运行查询,SELECT * FROM VK WHERE some filters则性能比情况 1 差

问题

  • 为什么表现如此不同?
  • 在情况 2 中如何提高性能?

我对提高案例 2 的性能很感兴趣,因为我需要一个视图来在我们的软件中使用 nHbinernate 进行映射......

提前致谢,问候

约翰艾伦的帖子后更新

好的,我尝试但没有结果。我不是 DBA,我在 DB 配置方面的技能非常有限。我们可以一步一步来吗?

  1. 在远程服务器 ( called Y) 上,我called linkedserver通过 security->logins->new login创建了一个新帐户 ( )。我选择登录名,然后选择 sql 身份验证,然后选择一个密码。对于默认数据库,我选择master. 在server roles选项卡中,我选择public. 在User mapping选项卡中选择我参与远程查询数据库,并为他们每个人,我选择db_ddladminpublic作用。然后,对于远程查询中涉及的每个数据库,我检查了链接服务器用户的有效权限,有很多ALTER很多CREATE权限但没有SHOW PLAN(然后我也选择了这个)。

  2. called XY 的链接服务器所在的数据库服务器 ( ) 上,我创建了一个链接服务器 ( called L1)。在安全选项卡,选择我local user saremote user linkedserver其密码。

当我在没有 VIEW 的情况下跨 L1 运行查询时,我得到了很好的结果,如果我将查询置于 VIEW 低性能中,则没有任何改变......

我想我做错了一步,但我不知道在哪里......

更清晰

这是我使用链接服务器在没有视图的情况下运行的查询:

select * from
(
    select * from dolph.agendasdn.dbo.vistaaccettazionegrp
    union
    select * from dolph.acampanet.dbo.vistaaccettazionegrp
    union
    select * from municipio.dbnet.dbo.vistaaccettazionegrp
) a 
where cognome = 'test' and nome = 'test'
Run Code Online (Sandbox Code Playgroud)

进入视图我只放了这段代码

    select * from dolph.agendasdn.dbo.vistaaccettazionegrp
    union
    select * from dolph.acampanet.dbo.vistaaccettazionegrp
    union
    select * from municipio.dbnet.dbo.vistaaccettazionegrp
Run Code Online (Sandbox Code Playgroud)

然后我打电话 select * from VIEW where cognome = 'test' and nome = 'test'

所以..

  • 第一种情况 0-1 秒。
  • 第二种情况 >15 秒...

我认为这很荒谬!

执行计划

带有普通查询的执行计划,不使用视图: 在此处输入图片说明

使用视图的执行计划: 带视图的执行计划

Roi*_*ish 5

您的问题以统计和估计开始和结束。我已经在我的服务器上重现了您的情况,并找到了一些有趣的提示和解决方法。

首先,让我们看一下您的执行计划:
当使用视图时,我们可以看到执行远程查询应用了过滤器,而没有视图则根本没有应用过滤器。事实是,在过滤器应用远程查询,在远程服务器,通过网络检索数据之前。
嗯,显然在远程服务器上应用过滤器从而检索更少的数据是一个更好的选择,显然只有在不使用视图时才会发生。

那么……有什么有趣的……?

令人惊讶的是,当我将过滤器从 更改cognome = 'test'cognome = N'test'(字符串的 Unicode 表示)时,视图使用了与第一个查询相同的执行计划。
我想使用查看SQL Server的估计,将有行从(远程)查询返回的少数时,和当地的过滤会比较便宜的原因是,不知何故,但是当SQL Server不得不隐转换NVARCHARVARCHAR,无法再使用统计数据,也没有做出在本地进行过滤的决定。
我在本地查找了统计信息,但该视图没有统计信息,所以我的猜测是该视图以临时查询没有的方式使用远程统计信息,并且做出了错误的决定。

好的,那怎么解决问题呢?

我之前说过有一种解决方法(至少在有人提出更好的解决方案之前),不,我不是说对字符串使用 unicode。
我想先给出一个答案,我仍然需要找出原因,但是当使用Inline FunctionSQL Server 时,其行为与查询(没有视图)完全相同,因此用函数替换视图将给出相同的结果,简单来说查询,并具有良好的性能(至少在我的环境中)。

我给你的代码建议是:

CREATE FUNCTION fn_anagrafiche2()
RETURNS table
AS
RETURN 
(
    SELECT * 
    FROM dolph2.agendasdn.dbo.vistaanagraficagrp
    UNION
    SELECT * 
    FROM dolph2.acampanet.dbo.vistaanagraficagrp
    UNION
    SELECT * 
    FROM municipio2.dbnet.dbo.vistaanagraficagrp
)
GO
Run Code Online (Sandbox Code Playgroud)

然后查询将是:

SELECT * 
FROM fn_anagrafiche2()
WHERE cognome = 'prova'
Run Code Online (Sandbox Code Playgroud)

这适用于我的服务器,但当然要先测试一下。
注意:我根本不建议使用SELECT *,因为它很容易在未来出现错误,我只是使用它,因为它在您的问题中,当我可以添加此评论时,我无需更改它:)