当我向其中添加WHERE子句时,是否优化了视图?


28

如果在视图内部或外部过滤视图,这会有所不同吗?

例如,这两个查询之间有什么区别吗?

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

要么

SELECT Id
FROM MyView
WHERE SomeColumn = 1

并且MyView定义为

SELECT Id, SomeColumn
FROM MyTable

如果源表位于链接服务器上,答案是否有所不同?

我之所以问是因为我必须从链接的服务器查询一个大表(4400万行)两次,并获得结果的汇总。我想知道是否应该创建两个视图来访问数据,每个查询一个视图,还是我可以放弃一个视图和一个WHERE子句。


1
如果只包含一个表,为什么还要使用视图呢?
HLGEM 2012年

3
@HLGEM安全吗?
JNK 2012年

2
@HLGEM视图实际上包含对不同服务器上的多个数据库的多个查询,并且它们通过进行联接UNION ALL。使用View比在需要数据时必须重写UNION查询要容易得多。
雷切尔2012年


1
@datagod,我会记住这一点,谢谢:)在这种情况下,有一个相当小的应用程序,它从一堆服务器中收集数据,运行一些计算并吐出一堆报告。它具有自己的数据库,因为某些计算会占用大量资源,因此我想将其与其他所有内容分开。
雷切尔2012年

Answers:


12

您应该看到这两个选择之间的计划或性能绝对没有区别。查询视图时,它会扩展为针对基表的查询,这意味着将使用相同的查找或扫描。

现在,根据的数据类型和选择性MyColumn,如果您想在基表上创建过滤索引(当您移至SQL Server 2008+时),您可能会获得更好的性能,但这在视图上不会有所不同或没有。


3
这个问题又是什么呢?这是在问为什么where视图外的子句的查询要比放在视图中的查询花费更长的时间?
雷切尔

1
如果视图不是出于性能考虑,那么它们只是出于结构考虑?
profimedica 2014年

1
出于性能原因,可以创建@profimedica 索引视图(例如,存储诸如聚合之类的中间结果,而不是在运行时进行计算)。如果未实现视图,则可能由于多种原因:DRY(在许多不同查询中执行的常见联接或筛选),安全性,混淆,架构简化。
亚伦·伯特兰

5

这只是一个简单的示例,说明应该没有区别。数据库就是AdventureWorks数据库。

两种视图定义:

create view Person.vContactWhere
as

    select *
    from person.Contact
    where ContactID = 24

go

create view Person.vContactNoWhere
as

    select *
    from person.Contact

go

这是第一个查询,该WHERE子句包含在视图定义中:

select *
from person.vContactWhere

这是执行计划:

在此处输入图片说明

第二个查询的WHERE子句不在视图定义中,而是在SELECT查询中:

select *
from person.vContactNoWhere
where ContactID = 24

这是执行计划:

在此处输入图片说明

从这些执行计划中可以看到,它们是相同的,但结果相同。我不知道这种逻辑/设计会得出不同结果的情况。因此,我愿意说您无论哪种方式都是安全的,并且可以根据个人喜好(或购买程序)选择。


1
这个问题又是什么呢?这是在问为什么where视图外的子句的查询要比放在视图中的查询花费更长的时间?
雷切尔

1
@Rachel我认为gbn在他的帖子和他所指的文章中对此做了很好的解释。我不知道该怎么办。
Thomas Stringer 2012年

我将其链接起来是因为在这种情况下,执行计划并不相同,这与您的回答不同。
雷切尔

1
@Rachel该示例中的问题是缺少转换规则。它不仅适用于视图,还适用于CTE和其他表表达式。在一般情况下,将谓词向下推到包含排名函数的表表达式中是无效的,因为这会改变结果。在这种情况下有效的原因是该Where子句适合PARTITION BY。SQL Server 2008似乎有一条SelOnSeqPrj识别此特殊情况的新规则。
马丁·史密斯


2

基于什么 ,SQL将确定执行计划时使用标准视图就像一个子查询。

因此,使用我的示例查询,

SELECT Id
FROM MyView
WHERE SomeColumn = 1

在哪里MyView定义为

SELECT Id, SomeColumn
FROM MyTable

它应该生成与执行计划相同的执行计划

SELECT Id
FROM 
(
    SELECT Id, SomeColumn
    FROM MyTable
) as T
WHERE SomeColumn = 1

但是此执行计划可能与生成的计划不同

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

我不确定此答案是否适用于索引视图


我认为这不是像这样的显式文本替换。
亚伦·伯特兰

@AaronBertrand您可能是对的。老实说,我不知道...我正在学习:)这种假设是基于我一直在阅读的其他有关视图如何像宏一样的东西。我稍微编辑了问题,以指定我是指标准视图,而不是索引视图。
雷切尔

@Rachel-替换发生在文本树级别的代词树上。
马丁·史密斯

@MartinSmith Hrrmm不是我所说的吗?执行计划应该相同,而不是案文相同?我不确定我是否了解“古树”
Rachel

这只是对您对Q本身的评论的回应,该评论说它“将View的文本插入到您的查询中”以及上面Aaron的评论。有关此处的解析/编译阶段的一些信息。实际上,您的答案确实也提到了文本替换。这是否值得区分。不确定!但是我想它解释了为什么sp_refreshview不需要文本替换概念。
马丁·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.