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

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

SELECT Id
FROM MyTable
WHERE SomeColumn = 1





SELECT Id
FROM MyView
WHERE SomeColumn = 1


MyView被定义为

SELECT Id, SomeColumn
FROM MyTable


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

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

评论

如果只包含一个表,为什么还要使用视图?

@HLGEM安全吗?

@HLGEM视图实际上包含对不同服务器上多个数据库的多个查询,并且它通过UNION ALL将所有查询连接在一起。使用View比在需要数据时必须重写UNION查询要容易得多。

另请参见stackoverflow.com/a/6654525/27535

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

#1 楼

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

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

评论


这个问题又是什么呢?这是在问为什么在视图外部使用where子句的查询要比在视图中放置时花费更长的时间?

–雷切尔(Rachel)
2012年3月21日19:07

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

– profimedica
2014年7月23日在16:19



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

–亚伦·伯特兰(Aaron Bertrand)
2014年7月23日在17:13

#2 楼

这只是一个简单的示例,说明应该没有区别。该数据库是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


这是执行计划:



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

评论


这个问题又是什么呢?这是在问为什么在视图外部使用where子句的查询要比在视图中放置时花费更长的时间?

–雷切尔(Rachel)
2012年3月21日19:07

@Rachel我认为gbn在他的帖子和他所指向的文章中对此进行了很好的解释。我不知道该怎么办。

–托马斯·斯金格
2012年3月21日19:19

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

–雷切尔(Rachel)
2012年3月21日在20:09

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

–马丁·史密斯
2012年3月21日在21:12



@Rachel-有关此问题的更多信息,请点击此处

–马丁·史密斯
13年10月10日在9:38

#3 楼

根据我正在阅读的内容,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


生成的计划不同。我不确定对于索引视图,此答案是否相同

评论


我认为这不是像这样的显式文本替换。

–亚伦·伯特兰(Aaron Bertrand)
2012年3月21日在18:19

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

–雷切尔(Rachel)
2012年3月21日在18:34

@Rachel-替换发生在文本树上而不是变色树上。

–马丁·史密斯
2012年3月21日18:49



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

–雷切尔(Rachel)
2012年3月21日18:53



这只是对您对Q本身的评论的回应,该评论说它“将View的文本插入到您的查询中”以及上面Aaron的评论。这里有一些关于解析/编译阶段的信息。实际上,您的答案确实也提到了文本替换。这是否值得区分。不确定!但是我想这解释了为什么需要sp_refreshview,而文本替换概念则不需要。

–马丁·史密斯
2012年3月21日18:56