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

时间:2008-10-26 05:14:34

标签: sql sql-server database refactoring

背景

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

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

总的来说,系统的代码(包括T-SQL代码)组织得不是很好,而且可以说是非常重构的。特别是,大多数表的模式都适用于所有类型的重构,小型(如列重命名)和大型(如规范化)。

FWIW,我有很长很好的应用程序开发经验(C / C ++,Java,VB和诸如此类的东西),但我不是DBA。所以,如果这个问题看起来很愚蠢,现在你知道为什么会这样。 : - )

问题

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

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

    此类附加计算列的典型(虽然简单)示例是从产品的常规价格和折扣中获得的产品的销售价格。

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

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

  3. 所以,基本上这是关于通过系统其他部分的视图隔离所有表

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

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

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

    • 您可以有效地为列名称添加别名。

    显然,所有这些好处都必须有一些代价,但我不确定我是否看到了潜伏在那里的所有渔获物。

    有人在实践中尝试过这种方法吗?有哪些主要缺陷?

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

    有没有人知道任何其他更强的弊端?

    例如,使用所有这些“包装”视图而不是表格很可能会对性能产生一些不利影响,但这种影响是否足以让人担心呢?此外,在使用ADODB时,即使只基于少数连接表,也很容易获得不可更新的记录集。那么,“包装”观点是否会使事情变得更糟?等等,等等......

    任何评论(特别是共享的真实体验)都将不胜感激。

    谢谢!


    P.S。我接下来讨论了“包装”视图的概念:

    The Big View Myth

    该文章建议避免上述方法。但是......我在文章中没有看到任何反对这个想法的充分理由。恰恰相反,在其创建视图的充分理由列表中,几乎每个项目都是为什么为每个表创建“包装”视图(特别是在遗留系统中,作为重构过程的一部分)如此诱人的原因)。

    这篇文章真的很旧(1999),所以无论什么理由都好,那么现在可能已经不再好了(反之亦然)。通过最新版本的SQL Server和MS Access,听到最近考虑过甚至尝试过这个想法的人真的很有意思......

3 个答案:

答案 0 :(得分:10)

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

  • 代码没有直接表访问(但可以从存储过程和视图和函数中获得)
  • 包含所有列的每个表的基本视图
  • 包含查阅列(类型,状态等)的每个表的扩展视图
  • 所有更新的存储过程
  • 任何复杂查询的功能

这允许DBA直接使用表(添加列,清理内容,注入数据等)而不会干扰代码库,并且它使代码库与对表所做的任何更改(临时或否则)

对于以这种方式做事可能会有性能损失,但到目前为止它们并没有那么重要 - 绝缘层的好处已经过几次救命了

答案 1 :(得分:4)

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

  

要重命名表列时

根据我的经验,这很少发生。添加列,删除列,更改索引和更改数据类型是您将运行的常用alter table脚本。

  

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

我会对此提出质疑。将计算放在列定义中并将其放在视图定义中有什么区别?此外,您会看到将其移动到视图而不是计算列的性能损失。唯一真正的优点是更改计算在视图中比通过更改表更容易(由于索引和数据页。)

  

您可以有效地为列名添加别名。

这是获得观点的真正原因;别名表和列,以及组合多个表。我过去几个工作中的最佳做法是使用我需要对数据进行非规范化的视图(查找等等,正如您已经指出的那样。)

像往常一样,对DBA问题的最真实回应是“它取决于” - 关于你的情况,技能等等。在你的情况下,重构“一切”将打破所有应用程序。如果您确实正确修复了基表,则不需要您尝试从视图中获取的间接,并且只会将架构维护的两倍用于将来的更改。我会说跳过包装器视图,修复表和存储过程(它们提供了足够的信息隐藏),你会没事的。

答案 2 :(得分:1)

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

我想补充说,视图很适合确保数据不会在项目中的Access表单之外更改。缺点是所有更新都需要存储过程 - 如果您还没有这些更新,则还必须创建它们。