嵌套视图是一个好的数据库设计吗?

Ric*_*nit 45 performance database-design sql-server view

我很久以前在某个地方读过。这本书指出我们不应该允许在 SQL Server 中使用嵌套视图。我不确定我们不能这样做的原因,或者我可能记得不正确的陈述。

学生们

SELECT studentID, first_name, last_name, SchoolID, ... FROM students

CREATE VIEW vw_eligible_student
AS 
SELECT * FROM students
WHERE enroll_this_year = 1
Run Code Online (Sandbox Code Playgroud)

老师

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
Run Code Online (Sandbox Code Playgroud)

学校

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
Run Code Online (Sandbox Code Playgroud)

在我的工作场所,我调查了我们的一个内部数据库应用程序。我检查了对象,发现有两到三层的视图相互堆叠。所以这让我想起了我过去读过的东西。有人可以帮忙解释一下吗?

如果这样做不行,我想知道它仅限于 SQL Server 还是一般用于数据库设计。

附加信息:我更新了我公司的一个例子。在没有太多技术性的情况下(在这个例子中有太多的列),我改变了一点,使其更通用。我们使用的嵌套视图大多基于抽象或聚合视图。例如,我们有一个包含数百列的大型学生表。说,Eligible Student View是基于今年入学的学生。学生符合条件的视图可以在其他地方使用,例如在存储过程中。

Nic*_*mas 49

无论平台如何,以下备注均适用。

(-) 嵌套视图:

  • 更难理解和调试

    例如,此视图列指的是哪个表列?让我深入挖掘4 个级别的视图定义......

  • 使查询优化器更难提出最有效的查询计划

    看到这个这个这个这个轶事证据。与此相比,这表明优化器通常足够聪明,可以正确解压缩嵌套视图并选择最佳计划,但并非没有编译成本。

    您可以通过将视图查询与针对基表编写的等效查询进行比较来衡量性能成本。

(+) 另一方面,嵌套视图让您:

  • 集中和重用聚合或业务规则
  • 抽象出您的底层结构(例如,从其他数据库开发人员那里)

我发现它们很少是必要的。


在您的示例中,您使用嵌套视图来集中和重用某些业务定义(例如“什么是合格学生?”)。这是嵌套视图的有效用途。如果您正在维护或调整此数据库,请权衡保留它们的成本与删除它们的成本。

  • 保留:通过保留嵌套视图,您会产生上面列举的优点和缺点。

  • 移除:移除嵌套视图:

    1. 您需要用它们的基本查询替换所有出现的视图。

    2. 如果您对符合条件的学生/教师/学校的定义发生变化,您必须记住更新所有相关查询,而不是仅更新相关视图定义。

  • 我不同意查询优化器的问题,因为无论经过多少次视图转换,解析所有视图后的结果查询都是相同的(除了中间结果集中的一些额外列,优化器可以很好地消除这些列)。这留下了调试;IMO 它使嵌套视图的调试更容易,因为我可以查看中间结果以查看哪里出错了。 (8认同)
  • 我编写了一个嵌入式数据库服务器,对我来说,首先解析视图然后优化结果查询是显而易见的途径,因为实际上视图上的所有查询都不太可能返回所有列。我什至想不出为什么在查询中间实现视图数据会有所收获,所以这对我来说是显而易见的。 (2认同)

Aar*_*and 27

有时嵌套视图用于防止重复聚合。假设您有一个对消息进行计数并按用户 ID 对它们进行分组的视图,您可能有一个视图来计算拥有 > 100 条消息的用户数量,诸如此类。当基本视图是索引视图时,这是最有效的 - 您不一定要创建另一个索引视图来表示具有稍微不同分组的数据,因为现在您要为索引维护支付两次费用,而性能可能是足以反对原观点。

如果这些都只是嵌套视图,您正在执行 select * 但更改排序或顶部,那么与一堆嵌套视图相比,这似乎更好地封装为带有参数(或内联表值函数)的存储过程。恕我直言。

  • “当基本视图是索引视图时,这是最有效的。” 很重要的一点。 (4认同)

bla*_*lah 7

SQL 的更高版本(2005+)似乎更擅长优化视图的使用。视图最适合整合业务规则。EG:我工作的地方有一个电信产品数据库。每个产品都被分配到一个费率计划,并且该费率计划可以被换出,并且随着费率的增加或修改,费率计划上的费率可以被激活/停用。

为了方便起见,我们可以制作嵌套视图。第一个视图只是使用任何需要的表将费率计划加入到他们的费率中,并返回下一级视图需要的任何必要数据。第二个视图只能隔离有效费率计划及其有效费率。或者,只是客户费率。或员工费率(员工折扣)。或者商业与住宅客户的价格。(费率计划可能会变得复杂)。关键是,基础视图确保我们的费率计划和费率的整体业务逻辑在一个位置正确连接在一起。下一层视图让我们更加关注特定的费率计划(类型、活动/非活动等)。

我同意如果您同时构建查询和视图,视图会使调试变得混乱。但是,如果您使用的是久经考验的可信任视图,它会使调试更容易。您知道该视图已经通过振铃器,因此您知道它很可能不会导致问题。

但是,您可以提出问题。“如果产品仅与不活动的费率计划相关联怎么办?” 或者“如果费率计划中只有非活动费率怎么办?” 嗯,这可以通过捕获用户错误的逻辑在前端级别捕获。“错误,产品处于无效费率计划中......请更正”。我们还可以运行查询审计以在计费运行之前对其进行仔细检查。(选择所有计划并离开加入活动费率计划视图,仅返回未获得活动费率计划的计划作为需要解决的问题)。

这样做的好处是视图可以让您大大压缩报告、计费等方面的查询。您可以拥有客户帐户视图,然后是仅活跃客户的第二级视图。根据客户地址进行团队合作。以产品为视角的团队(加入客户拥有的产品)。团队查看产品费率计划。根据产品功能进行团队合作。查看,查看,查看,每次试错以确保完整性。您使用视图的最终查询非常紧凑。

编辑:

作为视图如何比表格的平面查询更好的一个例子......我们有一个临时承包商进来进行一些更改。他们告诉他对事情有意见,但他决定平息他所有的疑问。Billing 正在处理他的一些查询。他们不断获得多个费率计划和费率。事实证明,他的查询缺少标准,仅允许在费率计划应该使用该/这些费率的开始日期和结束日期之间计费。哎呀。如果他使用了这个视图,它就会已经考虑到了这个逻辑。

基本上,您必须权衡性能与理智。也许你可以做各种花哨的事情来提高数据库的性能。但是,如果这意味着新人接手/维持是一场噩梦,真的值得吗?新来的家伙不得不玩打地鼠,必须找到所有需要改变逻辑的查询(并冒着忘记/粗指他们的风险)b/c 有人认为观点是“坏的”和没有将一些核心业务逻辑合并成一个可以在 100 个其他查询中使用的逻辑?这完全取决于您的业务和您的 IT/IS/DB 团队。但是,与性能相比,我更喜欢清晰度和单一来源的整合。


Ray*_*Ray 6

真正的问题不在于视图本身的嵌套。真正的问题是,随着开发人员对现有视图进行额外的调整,嵌套视图的激增。我发现带有 4 层嵌套视图的查询实际上连接到其定义中的视图之一。我们倾向于采取简单的方法而不是分析和解决问题,这才是问题的根源。