学生
SELECT studentID, first_name, last_name, SchoolID, ... FROM students
CREATE VIEW vw_eligible_student
AS
SELECT * FROM students
WHERE enroll_this_year = 1
老师
SELECT TeacherID, first_name, last_name, SchoolID, ... FROM teachers
CREATE VIEW vw_eligible_teacher
AS
SELECT * FROM teachers
WHERE HasCert = 1 AND enroll_this_year = 1
学校
CREATE VIEW vw_eligible_school
AS
SELECT TOP 100 PERCENT SchoolID, school_name
FROM schools sh
JOIN
vw_eligible_student s
ON s.SchoolID = sh.SchoolID
JOIN
vw_eligible_teacher t
ON s.SchoolID = t.SchoolID
在我的工作场所,我研究了我们的一个内部数据库应用程序。我检查了发现的对象,发现彼此之间有两三层视图堆栈。所以这让我想起了我过去读过的东西。任何人都可以帮忙解释一下吗?
如果这样做不合适,我想知道它仅限于SQL Server或通常用于数据库设计。
其他信息:
我更新了公司的示例。我进行了一些改动,使其变得更加通用,而没有太多的技术性(此示例中的列太多)。通常,我们使用的嵌套视图基于抽象或聚合视图。例如,我们有一个大学生表,其中有几百列。说,
Eligible Student View
基于今年入学的学生。符合学生资格的视图可以在其他地方使用,例如在存储过程中。 #1 楼
不论平台如何,以下说明均适用。(-)嵌套视图:
较难理解和调试
例如该视图列指的是哪个表列? Lemme挖掘了4个级别的视图定义...
使查询优化器更难提出最有效的查询计划
请参阅以下内容:这个,这个和这个作为传闻证据。与此进行比较,这表明优化器通常足够聪明,可以正确地解开嵌套视图并选择最佳计划,但并非没有编译成本。
您可以通过比较视图查询来衡量性能成本
(+)另一方面,嵌套视图使您可以:
集中和重用聚合或业务规则
抽象您的基础结构(例如,从其他数据库开发人员那里来)
我发现它们很少是必需的。
在您的示例中,您使用嵌套视图来集中和重用某些业务定义(例如“什么是合格的学生?”)。这是嵌套视图的有效用法。如果要维护或调整此数据库,请权衡保留它们与删除它们所花费的成本。
保持:通过保留嵌套视图,您会遇到上面列举的优点和缺点。
删除:删除嵌套视图:
您需要用其基本查询替换所有出现的视图。
您必须记住要更新如果您对符合条件的学生/教师/学校的定义发生了变化,则与所有相关查询相对,而不是仅更新相关视图定义。
评论
+1,除了我用“几乎不可能”将查询优化器的“更难的”替换为“几乎不可能的”。 :)
–詹森
2011年9月7日18:46
@Jason-我同意,我希望可以链接到一些具体示例。您是否知道任何解释或说明原因的参考文献?
–尼克·查马斯(Nick Chammas)
2011年9月7日19:09
我所能找到的只是轶事证据,当使用嵌套视图时,与“扁平化” SQL相比,它们会遇到性能问题。 sqlservercentral.com/blogs/2cents/archive/2010/04/05/…问题似乎归结为以下事实:DB(在这种情况下为SQL Server)在连接表之前不会应用某些过滤器,因此将使查询花费的时间比应该的长。
–詹森
2011年9月7日19:56
我不同意查询优化器的问题,因为解决了所有视图后生成的查询将是相同的,无论它经历了多少次视图转换(中间结果集中的一些额外列除外,优化器都可以消除这种情况)。剩下的调试工作; IMO可以简化嵌套视图的调试过程,因为我可以查看中间结果以查看出错的地方。
–西蒙·里希特(Simon Richter)
2011年9月8日下午0:52
我已经编写了一个嵌入式数据库服务器,对我来说,首先解析视图,然后优化结果查询是显而易见的路线,因为对视图的所有查询实际上都不可能返回所有列。我什至想不出为什么在查询中间实现视图数据会有所收获的原因,所以这对我来说很容易。
–西蒙·里希特(Simon Richter)
2011年9月8日在11:17
#2 楼
有时,嵌套视图用于防止重复聚合。假设您有一个视图,该视图可以对消息进行计数并按用户标识对消息进行分组,您可以在一个视图上对具有> 100条消息的用户数量进行计数。当基本视图是索引视图时,此方法最有效-您不一定要创建另一个索引视图来代表分组稍有不同的数据,因为现在您要为索引维护支付两次,而性能可能如果这些都是嵌套的视图,而您正在执行select *,但是更改顺序或顶部,则似乎最好将其封装为带有参数的存储过程(或内联表值函数),而不是一堆嵌套视图。恕我直言。
评论
“当基本视图是索引视图时,这最有效。”很重要的一点。
–尼克·查马斯(Nick Chammas)
2011-09-08 19:46
#3 楼
更高版本的SQL(2005+)似乎在优化视图使用方面更好。视图最适合合并业务规则。 EG:我在哪里工作,我们有一个电信产品数据库。每个产品都分配了一个费率计划,该费率计划可以换出,并且费率计划中的费率可以随着费率的增加或修改而被激活/去激活。为了简单起见,我们可以将其嵌套意见。第一个视图只是使用所需的任何表将费率计划与其费率结合起来,并返回下一级别的视图所需的任何必要数据。第二视图只能隔离活动费率计划及其活动费率。或者,只是客户费率。或员工费率(用于员工折扣)。或企业与住宅客户的费率。 (费率计划可能会变得很复杂)。关键是,基础视图可确保我们针对费率计划的整体业务逻辑和费率在一个位置正确地结合在一起。下一层视图使我们更加关注特定的费率计划(类型,活动/非活动等)。
我同意,如果您同时构建查询和视图,则视图会使调试变得混乱。 。但是,如果您使用的是try-n-trusted视图,它将使调试更加容易。您知道该意见已经通过了,因此您很可能不会引起问题。
问题可以提出您的意见。 “如果产品仅与无效的费率计划相关联,该怎么办?”或“如果费率计划仅包含无效费率,该怎么办?”好吧,这可以通过捕获用户错误的逻辑在前端级别捕获。 “错误,产品处于无效的费率计划中,请更正”。我们还可以运行查询审计以在开票之前对它进行仔细检查。 (选择所有计划并保留加入活动费率计划视图的权限,仅返回未获得活动费率计划的计划作为需要解决的问题)。
这样做的好处是,视图使您可以极大地简化查询以进行报告,计费等。您可以有一个客户帐户视图,然后是活跃客户的第二层视图。将其与客户地址组合在一起。以产品为视角进行团队协作(加入客户拥有的产品)。团队合作以查看产品费率计划。以产品功能为视角进行协作。查看,查看,查看每个审判错误,以确保完整性。使用视图的最终查询非常紧凑。
编辑:
作为一个示例,该视图将比仅对表进行平面查询更好。有一个临时承包商来做一些改变。他们告诉他对事情有看法,但他决定平息所有疑问。 Billing摆脱了他的一些疑问。他们不断获得多种利率计划和事物的利率。事实证明,他的查询缺少标准,仅允许费率在费率计划应在其开始和结束日期之间使用该费率时才计费。哎呀。如果他使用了该视图,那么该逻辑就已经考虑在内了。
基本上,您必须权衡性能与合理性。也许您可以做各种花哨的事情来提高数据库的性能。但是,如果这意味着新人接管/维持职位是一场噩梦,那真的值得吗?真的值得新家伙玩一玩,必须找到所有需要改变其逻辑的查询(并冒着忘记/发指的危险)的b / c某人认为视图“不好”并且难道没有将一些核心业务逻辑整合到可以用于100多个其他查询的逻辑中吗?这完全取决于您的业务和您的IT / IS / DB团队。但是,与性能相比,我更希望清晰度和单一源合并。
#4 楼
真正的问题不是嵌套视图本身。真正的问题是嵌套视图的泛滥,因为开发人员对现有视图进行了其他调整。
我发现带有嵌套视图的查询实际上已连接到4层它是定义中的一种观点。
我们倾向于采取简单的方法而不是分析和解决问题的趋势是问题的根源。
#5 楼
在我的环境中,我们将许多表从生产服务器复制到报表服务器。在报表服务器上,我们有大量基于复制生产表并嵌套的视图。在复制开始之前,我们必须删除所有视图以使复制成为可能(由于表结构在生产中经常发生变化,因此我们使用drop和create)。复制结束后,我们必须重建所有视图。
现在这是有趣的部分:
由于许多视图是嵌套的,因此我们必须在特定的视图中重建它们订购。在对视图定义进行任何更改时,我们必须注意保持正确的重建顺序。真是一团糟。如果您使用复制或只是删除并重建表(这些视图的源),我强烈不建议使用嵌套视图。
性能是另一回事。基于其他视图的视图只不过是要执行的多个查询。将较大的查询组合在一起,创建工作并从中创建表会更容易。更轻松并提高性能。
评论
我认为无论平台如何,相同的利弊大致相同。相关的StackOverflow帖子。