【问题标题】:Overnormalization过度规范化
【发布时间】:2010-09-22 12:14:33
【问题描述】:

数据库设计何时会被描述为过度规范化?这种特征是绝对的吗?还是取决于它在应用程序中的使用方式?谢谢。

【问题讨论】:

    标签: database rdbms normalization


    【解决方案1】:

    在一般意义上,我认为过度规范化是指当您执行如此多的 JOIN 来检索数据时,它会导致显着的性能损失和数据库死锁,即使您已经调整了索引。显然,对于像 MySpace 或 eBay 这样的大型应用程序和网站,去规范化是一项扩展要求。

    作为几家小型企业的开发人员,我告诉你,根据我的经验,从规范化 -> 非规范化总是比反过来更容易,实际上反过来(现在避免数据重复)一年左右后业务需求发生了变化)要困难得多。

    当我读到诸如“您应该将地址放在客户表中而不是单独的地址表中以便避免加入”之类的一般性陈述时,我不寒而栗,因为您只知道一年后有人会问您可以使用您完全没有预见到的地址做一些事情,例如维护审计跟踪,或为每个客户存储多个。如果您的数据库允许您创建索引视图,您可以回避这个问题,直到您的数据集太大以至于它不可能存在或无法由 1- 中的单个服务器或一组服务器提供服务。写,多读环境。对于我们大多数人来说,我认为这种情况不会经常发生。

    如果有疑问,我的目标是第三范式,但有一些例外(例如,让一个字段包含分隔字符串的 CSV 列表,因为我知道我永远不会从另一个角度查看数据)。当我需要整合时,我会先查看我的视图或索引。希望这会有所帮助。

    【讨论】:

    • 您至少应该瞄准 BCNF(基本上是 3NF 的一个版本,它消除了官方 3NF 没有的边缘情况),而且您经常会发现数据实际上是 5NF无论如何,这一点。
    • 值得注意的是,从 SQL Server 2005 开始,您可以使用 Inline-Table-Valued-Functions (ITVF)。您可以像表格一样加入这些并传入一些参数。建议您甚至可以从视图中查询并在 ITVF 中提供它可能听起来有些过头了,但是如果您发现自己使用相同的参数并在多个存储过程中一遍又一遍地连接,那么将其封装在致电 ITVF。
    • @JonathanLeffler 每个数据库都是不同的,所以像“始终瞄准 BCNF”这样的规则是禁忌的。标准化有好处,但也有缺点。您是否知道,在插入繁重的环境中,根据索引类型,插入索引列可能会产生显着的性能损失(不想在没有索引的情况下加入)?此外,连接不是免费操作,因此如果您要连接 1 个表以获取另一个表的子集,以此类推 8 深的链,连接性能可能会为大型表(>100M 记录)增加一些令人讨厌的开销。有时非规范化有好处。
    • @Nicholas Piasecki 我知道这篇文章已经有将近 11 年的历史了,但我只是想知道,您能否阐明规范化如何影响维护审计跟踪?谢谢。
    • @scrnjakovic 11 年后,我想我当时的想法是,在数据库中实现审计跟踪的一种常见方法(不是唯一方法)是使用“影子”表,其中您有 dbo.Customers 和 dbo.AuditCustomers,只要原始数据发生更改,就会在 AuditCustomers 中插入一个新行。如果您的数据被规范化,这意味着数据在一个地方被编辑并且审计很容易。如果它没有被规范化,那么你可能需要在多个地方更新它。
    【解决方案2】:

    这始终是应用领域的问题。这通常是一个正确性问题,但偶尔也是一个性能问题。

    在一种情况下,我可以想到一个初步的过度规范化案例:假设您有一个订单 + 订单项,订单项引用 productID,并将定价留给 product.price。由于这引入了时间耦合,因此您错误地进行了标准化,因为过度标准化会影响已发货的订单,除非价格绝对不会改变。您当然可以争辩说这只是一个建模错误(如在 cmets 中),但在大多数情况下,我也将归一化不足视为建模错误。

    另一个类别与性能相关。原则上,我认为通常有比非规范化数据更好的性能解决方案,例如物化视图,但如果您的应用程序遭受许多连接的性能后果,那么评估非规范化是否可以帮助您可能是值得的。我认为这些案例经常被过分强调,因为人们有时会在正确分析其应用程序之前就进行非规范化。

    人们还经常忘记替代方案,例如保持数据库的规范形式以及使用仓储或其他策略来处理经常读取但不经常更改的数据。

    【讨论】:

    • 时间耦合是一个很好的观点,并且在实施上线 30 天之前很容易被忽视。不是我去过那里。
    • 我喜欢你对替代品的强调。请注意,您的第一个案例根本与规范化无关。域设计师未能区分产品价格和销售价格。
    • @RoadWarrior - 是的,或者更准确地说,介于“当前产品价格”和“销售价格”之间。
    • 我认为第一个示例不是“过度标准化”,因为产品在逻辑上仍然可能具有当前价格,但建模不足,因为订单项目是(正如您指出的那样) 具有时间约束力,因此应该在销售时对价格进行快照。
    • 所有这些都是公平的观点,尽管可能是定义问题。对我来说,过度标准化包括正确性受到损害的情况(由于建模不佳)。除非采取预防措施,否则非规范化模式会损害正确性。
    【解决方案3】:

    标准化是绝对的。数据库遵循范式,或者不遵循。有六种范式。大多数情况下,他们的名字从第一到第五。另外还有一个 Boyce-Codd 范式。

    规范化仅出于一个目的——防止“更新异常”。

    标准化不是主观的。这不是判断。每个表和表之间的关系要么遵循规范形式,要么不遵循规范形式。

    因此,您不能“过度规范化”或“规范化不足”。

    话虽如此,归一化有性能成本。有些人选择以各种方式进行非规范化以提高性能。最常见的合理非规范化是打破 3NF 并包含派生数据。

    一个常见的错误是破坏 2NF 并在键值和非键值之间存在函数依赖的重复副本。这需要额外的更新,或者——更糟糕的是——触发以保持副本并行。

    事务性数据库的非规范化应视具体情况而定。

    数据仓库也很少遵循任何事务规范化规则,因为它(基本上)从未更新。

    “过度规范化”可能意味着数据库由于大量连接而太慢。这也可能意味着数据库已经超出了硬件。或者应用程序没有被设计为可扩展的。

    这里最常见的问题是人们在交易进行时尝试使用交易数据库进行报告。事务的锁定会干扰报告。

    然而,“Under-normalization”意味着存在 NF 违规,并且正在进行不必要的处理来处理复制数据和纠正更新异常。

    【讨论】:

    • 你不能“过度规范化”或“规范化不足”,但“过度规范化”可能意味着......然而,“Under-normalization”意味着...... 虽然两者都有帮助,但我不确定该相信哪个@SLott。 ;^)
    • 原来更新异常首先在 ETNF(Fagin & Date 2012)在 4NF 和 5NF 之间停止(并且在它和 5NF 之间已经有无异常的 NF)。但是 5NF 消除了进一步的冗余情况,其中一个表可以方便地替换为 3 个或更多连接回它的表。
    【解决方案4】:

    当性能成本超过应用程序预期用途的收益时。

    【讨论】:

    • 我一直很喜欢“规范化'直到它受伤,非规范化'直到它起作用”这句话。 :)
    • 正是——完美的平衡。
    • 一个非常好的声明 vfilby。它用一个清晰​​简单的句子总结了我在下面的评论。 :)
    【解决方案5】:

    规范化您的 OLTP 数据库,并非规范化您的 OLAP 数据库。每个人都有一个决定其架构的使命。与规范化事务数据库一样,数据仓库的存在也是有原因的。一个完整的系统需要两者。

    【讨论】:

      【解决方案6】:

      很多人都在谈论性能。我认为一个关键问题是灵活性。一般来说,你的数据库越规范化,它就越灵活。

      我们目前使用“过度规范化”的数据库,因为在我们的操作环境中,客户需求每月都会发生变化。通过“过度规范化”,我们可以相应地采用我们的软件,而无需更改数据库结构。

      【讨论】:

      • 我完全同意。我使用过具有数百万条记录的数据库,性能从来都不是问题。数据的结构需要足够灵活,以允许多种不同的用途和不断变化的需求,而无需更改数据结构。规范化就是这个问题的答案。
      【解决方案7】:

      我对此的看法:

      总是尽可能地标准化。我通常对规范化很着迷,并尝试设计一些可以处理所有可以想到的未来扩展的东西。我最终得到的是一个非常灵活的数据库设计......而且不可能实现。

      然后真正的工作开始了:去规范化。在这里,您可以解决您知道实施起来会出现问题和/或会因为连接过多而减慢查询速度的问题。

      这样你就知道你为了什么让设计可用。

      编辑:文档!我忘了提到记录非规范化非常重要。当您接管一个项目以了解选择背后的原因时,这非常有帮助。

      【讨论】:

      • “每一个可以想到的未来扩展”都是多余的;最多你需要处理可能的扩展(不是那些可能的)。这是敏捷技术的一部分——不要太担心未来。使用 DBMS,对未来的一些担忧是好的,但不会太多。
      • 我明白你的意思,但我相信 DBMS 的设计是项目中最基础的部分。在该级别上犯的错误是以后最难纠正的错误,因为重新设计数据库很可能会破坏大部分代码。
      【解决方案8】:

      第三范式 (3NF) 被认为是许多理性数据库应用程序的最佳规范化级别。在这种状态下,as Bill Kent once summarized,每个 " 非键字段 [在特定关系数据库管理系统或 RDBMS 中的每个表中] 必须提供有关键的事实,整个键,并且什么都没有但关键。” 3NF 是introduced by E.F. Codd 的一个术语,他是数据库管理关系模型的发明者。通常,软件应用程序所依赖的数据,尤其是用于在线事务处理系统 (OLTP) 的应用程序,将在 3NF 中表现良好。根据定义,这种范式通过要求行/列数据的最小重复来减小数据库大小,并最大限度地提高查询效率和应用程序维护的便利性。 3NF 通过要求将数据库的表(即它的模式)分解为由主键/外键相关的单独表来实现这一点——基本上直到 Kent 的规则成立(好吧,我已经这样说是为了便于阅读,但是3NF 的实际定义比这要详细得多)。相比之下,过度规范化意味着增加相关表之间查询所需的连接数。这是由于将数据库模式分解为比 3NF 更细化的级别。然而,尽管超过 3 度的归一化通常可以被认为是过度归一化,但“过度归一化”一词的负面含义有时可能是没有根据的。由于应用程序软件的复​​杂性和多功能性,在某些设计上需要 4NF(及以上)的应用程序中可能需要过度规范化。这方面的一个例子是针对某些行业的高度可定制和可扩展的商业数据库程序,在该程序中它被出售给需要开放 API 的最终用户。但是反过来也可能是可取的 - 即非规范化 - 最值得注意的是,当设计一个在线分析处理 (OLAP) 数据库时,它严格用于汇总来自 OLTP 数据库的数据,仅用于查询/报告 - 例如数据仓库。在这种情况下,数据必须以高度非规范化的格式(即 1NF 或 2NF)存在。通常在这些限制下——当对高效查询和报告有很高的要求时——我们发现数据库和应用程序程序员调用数据库,“过度规范化”。但是正如Redgate's Tony Davis once said——考虑到当今更先进、更高效的数据库软件和存储系统——“查询中的多个连接对性能的影响可以忽略不计。如果你的数据库很慢,那不是因为它是'过度标准化'!”所以总而言之,这种特性——超标准化——不是绝对的,它取决于它在应用程序中的使用方式。 In Kent's words, "规范化规则旨在防止更新异常和数据不一致...... [但是] 在考虑到实际性能要求时,没有义务对所有记录进行完全规范化......规范化设计增强了数据的完整性,通过最小化冗余和不一致性,但在某些检索应用程序中可能会付出一些性能成本...... [因此,] 标准化的可取性必须根据其对检索应用程序的性能影响来评估。 em>"

      【讨论】:

        【解决方案9】:

        【讨论】:

        • 这是一个有缺陷或玩具的 DBMS - 是时候用真正的 DBMS 替换它了。
        • Pfft .. 每个人都知道“真正的”RDMS 应该进行数万亿次连接。限制是针对懦夫的。任何无法处理一万亿连接的东西......必须是一个“玩具”!
        【解决方案10】:

        如果连接过多会影响性能,则为报告目的创建非规范化表可以加快处理速度。通过将数据复制到新表中,可以运行完全没有连接的报表。

        【讨论】:

          【解决方案11】:

          根据我的经验,我从未见过包含邮政地址的规范化数据库,因为将地址存储为字符串通常是可以接受的。理想情况下,会有国家、县/州、城市、地区和街道的表格。我没有遇到任何需要在街道上报告的人,所以没有必要。这些地址仅用于邮政联系,因此被视为一个实体。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-05-22
            • 1970-01-01
            • 2013-08-21
            • 2016-05-13
            • 2018-06-06
            • 2010-12-29
            • 2016-05-30
            相关资源
            最近更新 更多