2010-11-03 111 views
22

使用SqlServer Views有什么缺点?使用SqlServer视图有什么缺点?

我经常创建视图以非规范化的形式显示我的数据。

我发现它更容易,因此更快,更容易出错,更多的自我记录,查询这些连接之一,而不是生成复杂的查询与许多表之间的复杂连接。特别是当我从不同角度分析相同的数据(许多相同的字段,同一表连接)时。

但是,创建和使用这些视图是否有成本?

我是放慢(或加速?)查询处理?

+1

+1根据我的经验有无知和误传分贝的意见数量惊人的。可能会有很多关于哪些视图做什么以及如何做的讨论,但是我不确定它们是否被这样构建,以及答案是否明显。 – 2010-11-03 14:00:06

+18

@Mr Shoubs - 我认为人们在这里提出问题,即使答案很容易被搜索到,因为他们希望提供的交互性和后续/问答,我不认为我们应该劝阻。 – JNK 2010-11-03 14:00:12

+0

@保罗 - 打我吧! – JNK 2010-11-03 14:00:36

回答

18

当谈到视图有优点和缺点。

优点:

  1. 它们是虚拟表,而不是存储在数据库中作为不同的对象。所有存储的都是SELECT语句。
  2. 它可以作为一种安全措施,通过限制用户可以看到的内容。
  3. 它可以通过将常用复杂查询封装到视图中来使其更容易阅读。尽管如此,这是一把双刃剑 - 见缺点#3。

缺点:

  1. 它没有高速缓存,所以它不会是一样快的存储过程优化的执行计划。
  2. 由于它基本上只是一个SELECT的抽象,所以比纯粹的SELECT稍微慢一些。
  3. 它可以隐藏复杂性并导致陷入困境。 (请注意:ORDER BY not honored)。

我个人的观点是不使用视图,而是使用存储过程,因为它们提供视图的安全性和封装性,而且还具有改进的性能。

+4

我认为最大的危险来自劣势#3。隐藏的复杂性是潜在的危险。通常情况下,使用视图的目的是“简化”,但从长远来看最终会产生更多问题。 – GrowlingDog 2010-11-03 15:27:09

+2

你能否解释ORDER BY not Honored Gotcha以及它如何体现自己。如果你想回答,我有一个问题。 http://stackoverflow.com/questions/5901558/is-order-by-honoured-in-sql-server-views – 2011-05-05 17:23:57

7

视图的效率很大程度上取决于底层表。该视图实际上只是一种有组织的一致方式来查看查询结果。如果用于形成视图的查询很好,并且在基础表上使用适当的索引,则视图不应该对性能产生负面影响。

在SQL Server中,您也可以使用create materialized or indexed views(因为SQL Server 2000),这会提高速度。

+1

一如既往,未归因和未注释的downvotes表示赞赏:P – JNK 2010-11-03 15:35:23

4

我也经常使用视图。但是需要注意的是,如果您的基础表经常变化(尤其是在开发过程中),那么使用大量视图可能难以维护。

编辑:话虽如此,我发现能够简化和重复使用复杂查询的便利和优势胜过维护问题,尤其是在负责任地使用视图的情况下。

1

当我开始时,尽管视图增加了性能开销,但是体验描绘了一个不同的故事(视图机制本身的开销可以忽略不计)。

这一切都取决于底层查询是什么。退房索引视图herehere,最终你应该测试性能两种方式获得清晰的性能配置

+0

Dude ...放弃态度和证明y我们的贴子.... – 2010-11-03 14:04:46

+0

好的,好吧,谈论被跳 - 我听起来很糟糕,然后打算 – 2010-11-03 14:06:23

+0

@Mr Shoubs。也许很多信息,但也可能是太多的信息。我不想花费3天时间阅读数百页文档。我只想要一个简单的答案。我想我可以要求一个好的链接,让我回答这个问题。然后依靠那些得票最多的人。 – 2010-11-03 16:53:09

3

一个缺点的看法,我已经在性能上把它们纳入到分布式查询时遇到的一个潜水。这篇文章讨论了 - 虽然我在演示中使用了高度人造的数据,但我在“现实世界”中一次又一次地遇到了这个问题。

尊重你的意见,他们会很好的对待你。

10

使用视图的一个可能的不利之处是你抽象了底层设计的复杂性,这可能导致初级开发人员和报表创建者的滥用。

对于一个特别大且复杂的项目,我设计了一组视图,这些视图主要由报告设计人员用来填充水晶报表。几周后,我发现初级开发者已经开始使用这些视图来获取聚集并加入这些已经很大的视图,因为他们在那里并且很容易被使用。 (数据库中有一个强大的EAV设计元素。)在初级开发人员开始询问为什么看似简单的报告需要花费很多分钟才能执行之后,我发现了这一点。

4

当视图包含逻辑,列,行或表最终未被最终查询使用的表时,视图可能会损害性能。我不能告诉你有多少次我看到的东西,如:

SELECT ... 
FROM (View with complex UNION of ActiveCustomer and InactiveCustomer tables) 
WHERE Active = True 

(从而筛选出包括在从InactiveCustomer表中的观点,即所有行),或

SELECT (one column) 
FROM (view that returns 50 columns) 

( SQL必须检索大量数据,然后在后面的步骤丢弃的,其可能与其他列是昂贵的检索,想通过书签查找),或

SELECT ... 
FROM (view with complex filters) 
WHERE (entirely different filters) 

(它可能是SQL可以有使用,如果表被直接查询更适当的指数), 或

SELECT (only fields from a single table) 
FROM (view that contains crazy complex joins) 

(大量的CPU开销通过加入,和不必要的IO为表读取稍后丢弃),或我喜欢的:

SELECT ... 
FROM (Crazy UNION of 12 tables each containing a month of data) 
WHERE OrderDate = @OrderDate 

(仅当真正需要读取1时才读取12个表格)。

大多数的情况下,SQL足够聪明,可以“查看封面”并提出有效的查询计划。但在其他情况下(特别是非常复杂的情况下),它不能。在上述每种情况下,答案都是删除视图并查询基础表。

最起码(即使你认为SQL将足够聪明反正去优化它),消除了看法有时会令自己的查询调试和优化更容易(更明显一点需要做什么) 。

+0

不知道是什么问题:SELECT ... 从(查看与疯狂联合主动和无效客户) WHERE Active = True。你是否应该说还有两个视图,一个是所有活跃客户,另一个是非活动客户。所以如果你只需要激活你查询'活跃'视图等? – 2010-11-03 16:47:03

+0

@Lill好吧,在这个(做作)的例子中,视图组合了来自表格的数据,然后由最终查询过滤出来。所以直接查询ActiveCustomer表,并完全绕过视图。 – BradC 2010-11-03 17:05:52

+0

编辑过的帖子,使这个例子更清晰。 – BradC 2010-11-03 17:23:35

0

我最大的'抱怨'是,ORDER BY不能在视图中工作。虽然这是有道理的,但如果没有预料到的话,它可能会跳起来咬人。因此,我必须将切换到使用视图到SPROCS(它们有足够多的问题),在某些情况下,我无法在以后指定ORDER BY。 (我希望有一个带有“最终视图”的构造 - 例如可能包括按语义排序)。

http://blog.sqlauthority.com/2010/10/03/sql-server-the-limitations-of-the-views-eleven-and-more/(限制#1是关于ORDER BY :-)

2

什么是SQL Server中的视图的各种限制?

观前11局限性

  • 视图不支持COUNT();但是,它可以支持COUNT_BIG(
  • ORDER BY子句中查看不起作用
  • 定期查询或存储过程给我们的灵活性,当我们需要另一列;我们可以立即为常规查询添加一列。如果我们想要对视图执行相同的操作,那么我们必须先修改它们
  • 视图上创建的索引不常用
  • 一旦创建了视图并且基本表中添加或删除了任何列,通常不反映在视图,直到它被刷新
  • UNION操作无法在索引视图允许
  • 我们不能创建一个嵌套的查看情况的指数意味着我们不能从另一视图建立了一个视图中创建索引。
  • 自连接不能在索引视图允许
  • 外索引视图加入不允许
  • 跨数据库查询在索引视图中不允许

来源SQL MVP皮纳尔戴夫

http://blog.sqlauthority.com/2010/10/03/sql-server-the-limitations-of-the-views-eleven-and-more/

-2

以下是允许在视图中引用命令的SQL hack:

create view toto1 as 
select top 99.9999 percent F1 
from Db1.dbo.T1 as a 
order by 1 

但我的偏好是使用Row_Number

create view toto2 as 
select *, ROW_NUMBER() over (order by [F1]) as RowN from ( 
select f1 
from Db1.dbo.T1) as a