多个连接视图中的多个重复 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
一开始有一套 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