例如,这两个查询之间有什么区别吗?
SELECT Id
FROM MyTable
WHERE SomeColumn = 1
SELECT Id
FROM MyView
WHERE SomeColumn = 1
MyView
被定义为SELECT Id, SomeColumn
FROM MyTable
并且答案是否有不同,如果源表位于链接服务器上吗?
我问,因为我必须从链接服务器查询一个大表(4400万行)两次,并汇总结果。我想知道是否应该创建两个视图来访问数据,每个查询一个视图,还是我可以摆脱一个视图和一个
WHERE
子句。#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
评论
如果只包含一个表,为什么还要使用视图?@HLGEM安全吗?
@HLGEM视图实际上包含对不同服务器上多个数据库的多个查询,并且它通过UNION ALL将所有查询连接在一起。使用View比在需要数据时必须重写UNION查询要容易得多。
另请参见stackoverflow.com/a/6654525/27535
@datagod我会记住这一点,谢谢:)在这种情况下,有一个相当小的应用程序,它从一堆服务器中收集数据,运行一些计算并吐出一堆报告。它具有自己的数据库,因为某些计算会占用大量资源,因此我想将其与其他所有资源分开。