多个连接视图中的多个重复 EXISTS 语句是否会在 SQL 服务器中得到优化

Would multiple repeated EXISTS statements that are in multiple joined views get optimised in SQL Server

一开始有一套 table 供所有第三方使用,数据库很好....然后...

我们的第 3 方之一需要公开他们的一些数据,以便隐藏所有其他客户数据解决方案是创建另一组 tables(!!!),我们将为此复制数据第 3 方并仅授予他们镜像 table 组的访问权限....直到另一个第 3 方要求相同...然后另一个...然后我进来了...

ATM 我正在​​考虑为每个第 3 方引入一组 Views,它们位于自己的第 3 方 Schema 中,并从原始 table 中进行子选择...在新 Views 中确定要向我计划介绍的人显示哪些记录 RecordOwner table。对于需要在该特定视图集中显示的记录,我将在其中设置 PK 和所有者列。 (其他选项是添加到包含 PK 的 'main' table 添加所有者列并从那里识别所有者....但我认为这不太灵活...)

我的视图看起来像这样(名称仅供说明):

CREATE VIEW [3rdPartyTable]
AS
   SELECT *
   FROM [OriginalTable] ot
   WHERE EXISTS (SELECT 1 FROM [RecordOwner] 
                 WHERE [Id] = ot.[Id] AND [Owner] = 'Owner1')

CREATE VIEW [3rdPartyTable2]
AS
    SELECT *
    FROM [OriginalTable2] ot
    WHERE EXISTS (SELECT 1 FROM [RecordOwner] 
                  WHERE [Id] = ot.[MasterId] AND [Owner] = 'Owner1')

我在考虑性能,因为在那些原始 table 中有相当多的几百万条记录。当每个第 3 方将 运行 他们的查询并加入他们的观点时 SQL 服务器将足够聪明以优化多个相同的重复

where exists (select 1 from [RecordOwner] 
              where [Id] = ot.[MasterId] and [Owner] = 'Owner1')

要不要?

编辑: 考虑第 3 方开发人员写的以下查询:

SELECT * from [3rdPartyTable2] t2 
inner join [3rdPartyTable3] t3 on t2.MasterId = t3.Masterid 

这将转化为

SELECT * FROM
   (SELECT * FROM [OriginalTable2] ot 
   where exists (select 1 from [RecordOwner] where [Id] = ot.[MasterId] and [Owner] = 'Owner1')) t2
inner join 
   (SELECT * FROM [OriginalTable3] ot 
   where exists (select 1 from [RecordOwner] where [Id] = ot.[MasterId] and [Owner] = 'Owner1')) t3
on t2.MasterId = t3.Masterid 

并且两个 table 在 MasterId 上都有 PK。

SQL 服务器是否足够智能以优化视图中多个重复的 EXISTS 子句?

评论太长了。

你在说什么?您的 exists 表达式正在使用相关子查询。因此,每个都是一个单独且不同的查询,因为它们在外部查询中引用不同的表。

有了 RecordOwner(Id, Owner) 上的索引,性能应该没问题。但是,你应该测试一下。

您也可以考虑为每个客户端编写一个单独的 视图。客户端可能更愿意访问称为 table_client 的东西,而不是依赖于隐藏的安全机制。

TL;DR; 使用 JOINS 构建的视图与使用 EXISTS 构建的视图相同或更快(并且它们确实得到了优化在 LEFT OUTER JOINS).

为了证实@Gordon的回答,我做了实验,做了视图,索引,填充了数据库中93%的PK记录数据,从执行计划可以看出,join 3张表时,扫描了3次。 ...

尽管开销很小(每个连接约 3%)...

编辑: 运行 另一组测试和执行计划在加入 LEFT OUTER JOIN 视图时是相同的,但在执行 INNER JOINS 视图时使用 JOIN 而不是 EXISTS 构建优于后者...

JOIN 的视图示例:

CREATE VIEW [dbo].[Summary2]
AS
SELECT st.*
  FROM [OriginalSummary] st
  inner join [RecordOwner] ro on ro.[Id] = st.[MasterId] and [Owner] = 'corp1'

带有 EXISTS 的视图示例:

CREATE VIEW [dbo].[Summary]
AS
SELECT *
FROM [OriginalSummary] ot
WHERE EXISTS (SELECT 1 FROM [RecordOwner] 
              WHERE [Id] = ot.[MasterId] AND [Owner] = 'corp1')
GO