代码之家  ›  专栏  ›  技术社区  ›  Yarik

SQL Server 2005:按视图包装表-优缺点

  •  8
  • Yarik  · 技术社区  · 16 年前

    背景

    我正在开发一个遗留的小型企业自动化系统(库存、销售、采购等),它有一个由SQL Server 2005托管的单一数据库和一组客户端应用程序。主客户端(所有用户都使用)是MS Access 2003应用程序(ADP),其他客户端包括各种VB/VBA应用程序,如Excel加载项和命令行实用程序。

    除了60个左右的表(大部分在3nf中),数据库还包含大约200个视图、大约170个UDF(主要是标量和表值内联视图)和大约50个存储过程。正如您可能已经猜到的,所谓的“业务逻辑”的某些部分被封装在这一大堆T-SQL代码中(因此被所有客户机共享)。

    总的来说,系统的代码(包括T-SQL代码)没有很好的组织,而且很难重构。尤其是,大多数表的模式都要求进行各种重构,小的(如列重新命名)和大的(如规范化)。

    FWWW,我有相当长的和不错的应用程序开发经验(C/C++、Java、VB和WHATNOT),但我不是DBA。所以,如果你觉得这个问题很愚蠢,现在你知道为什么会是这样了。-)

    问题

    在考虑重构所有这些混乱的时候(当然是以和平方式),我提出了以下想法:

    1. 对于每个表,创建一个“包装”视图,该视图(a)包含表中的所有列;以及(b)在某些情况下,具有基于表的“实”列的其他计算列。

      这种额外计算列的一个典型(尽管简单)示例是从产品的正常价格和折扣中得出的产品的销售价格。

    2. 重新组织所有代码(T-SQL和VB/VBA客户端代码),以便只有“包装器”视图直接引用表。

      因此,例如,即使应用程序或存储过程需要从表中插入/更新/删除记录,它们也会针对相应的“表包装器”视图执行此操作,而不是直接针对表。

    所以,本质上这是关于 按视图将所有表与系统其余部分隔离 .

    这种方法似乎提供了很多好处,特别是从可维护性的角度来看。例如:

    • 当要重命名表列时,可以在不同时重写所有受影响的客户机代码的情况下进行。

    • 更容易实现派生属性(比使用计算列更容易)。

    • 您可以有效地使用列名的别名。

    显然,所有这些福利都必须有一定的价格,但我不确定我是否看到了所有的渔获量都潜藏在那里。

    有人在实践中尝试过这种方法吗?主要的陷阱是什么?

    一个明显的缺点是维护“包装”视图与其对应表同步的成本(表中的新列也必须添加到视图中;从表中删除的列也必须从视图中删除;等等)。但是,这个价格对于提高整体代码库的弹性似乎是很小和公平的。

    有人知道其他更强大的缺点吗?

    例如,使用所有这些“包装器”视图(而不是表)很可能会对性能产生一些不利影响,但这种影响是否足以让人担心呢?另外,在使用ADODB时,很容易得到一个不可更新的记录集,即使它仅仅基于几个联接的表;那么,“包装器”视图会使情况变得更糟吗?等等,等等……

    任何评论(特别是分享真实经验)都将受到极大的赞赏。

    谢谢您!


    P.S.我在下面的老文章中讨论了“包装器”视图的概念:

    The Big View Myth

    本文建议避免使用上述方法。但是…我在这篇文章中没有看到任何反对这个想法的好理由。恰恰相反,在创建视图的良好理由列表中,几乎每一项都正是它如此诱人地为每个表(尤其是在遗留系统中,作为重构过程的一部分)创建“包装器”视图的原因。

    这篇文章真的很老(1999年),所以无论什么原因是好的,那么现在可能不再好了(反之亦然)。如果最近有人考虑或尝试过这个想法,并使用最新版本的SQL Server和MS Access,那么您会非常感兴趣…

    3 回复  |  直到 16 年前
        1
  •  10
  •   Steven A. Lowe    16 年前

    在设计数据库时,我更喜欢以下内容:

    • 代码不能直接访问表(但在存储过程、视图和函数中可以)
    • 包含所有列的每个表的基视图
    • 包含查找列(类型、状态等)的每个表的扩展视图。
    • 所有更新的存储过程
    • 用于任何复杂查询的函数

    这允许DBA直接处理表(添加列、清理内容、注入数据等),而不会干扰代码库,并且它将代码库与对表所做的任何更改(临时或其他)隔离开来。

    这样做可能会对性能造成影响,但到目前为止,这并不重要——绝缘层的好处是可以多次挽救生命。

        2
  •  4
  •   Rick    16 年前

    您不会注意到对一个表视图的任何性能影响;在为使用这些视图的任何代码构建执行计划时,SQL Server将使用基础表。我建议您使用模式绑定这些视图,以避免在不更改视图的情况下意外更改基础表(想想可怜的下一个家伙)。

    当要重命名表列时

    根据我的经验,这种情况很少发生。添加列、删除列、更改索引和更改数据类型是您将要运行的通常的更改表脚本。

    更容易实现派生属性(比使用计算列更容易)。

    我对此表示怀疑。将计算放入列定义和将其放入视图定义之间有什么区别?此外,您还将看到将其移动到视图而不是计算列的性能会受到影响。唯一的真正优势是 改变 在视图中计算比更改表(由于索引和数据页)更容易。

    您可以有效地使用列名的别名。

    这就是拥有视图、表和列别名以及组合多个表的真正原因。在我过去的几项工作中,最佳实践是在需要将数据非规范化的地方使用视图(如您已经指出的查找等)。

    像往常一样,对DBA问题最真实的回答是“它取决于”——取决于您的情况、技能等。在您的情况下,重构“一切”无论如何都会破坏所有应用程序。如果您确实正确地修复了基表,那么您试图从视图中获得的间接寻址就不需要了,而且对于将来的任何更改,模式维护只需要增加一倍。我想说,跳过包装视图,修复表和存储的过程(这些过程已经提供了足够的信息隐藏),这样就可以了。

        3
  •  1
  •   Community datashaman    7 年前

    我同意 Steven's comment --主要是因为您使用的是Access。在重新设计数据库时,保持访问的优缺点非常重要。我去过那里,通过访问前端/SQL服务器后端(尽管它不是ADP项目)完成了这项工作。

    我想补充一下,视图对于确保数据不会在项目中的访问表单之外发生更改是很好的。缺点是所有更新都需要存储过程——如果您还没有这些更新,那么也必须创建它们。