您如何确定数据库规范化的程度?
Posted
技术标签:
【中文标题】您如何确定数据库规范化的程度?【英文标题】:How do you determine how far to normalize a database? 【发布时间】:2010-09-08 01:02:14 【问题描述】:在创建数据库结构时,有哪些好的指导方针或好的方法可以确定数据库应该规范化到什么程度?您是否应该创建一个未规范化的数据库并随着项目的进行将其拆分?您是否应该根据性能需要创建完全规范化的表格并组合表格?
【问题讨论】:
【参考方案1】:您想开始设计一个规范化的数据库,最高可达第 3 范式。在开发业务逻辑层时,您可能会决定必须进行一些非规范化,但永远不要低于第三种形式。始终保持第一种和第二种形式的合规性。您希望为了代码的简单性而不是为了性能而进行非规范化。为此使用索引和存储过程:)
没有“随手规范化”的原因是每次修改数据库设计时都必须修改已经编写的代码。
有几篇不错的文章:
http://www.agiledata.org/essays/dataNormalization.html
【讨论】:
链接到相关的answer,注意性能驱动的非规范化发生在索引和查询优化之后。 @onedaywhen 错了。 3NF 不属于 BCNF。有cases where 3NF is attainable and BCNF isn't。【参考方案2】:@GrizzlyGuru 一位智者曾经告诉我“正常化直到它受伤,非正常化直到它起作用”。
它还没有让我失望:)
我不同意以非规范化的形式开始使用它,但是,根据我的经验,它更容易调整您的应用程序以处理规范化程度较低的数据库而不是规范化程度更高的数据库。它还可能导致其工作“足够好”的情况,因此您永远无法对其进行规范化(直到为时已晚!)
【讨论】:
【参考方案3】:规范化意味着消除冗余数据。换句话说,非规范化或非规范化数据库是相同信息将在多个不同位置重复的数据库。这意味着您必须编写更复杂的更新语句以确保您在各处更新相同的数据,否则您会得到不一致的数据,这反过来意味着查询的输出不可靠。
这是一个相当大的问题,所以我会说非规范化很痛苦,而不是相反。
在某些情况下,如果您认为好处超过了更新数据的额外工作和数据损坏的风险,您可能会故意决定对数据库的特定部分进行非规范化。例如,对于数据仓库,出于性能原因汇总数据,并且如果在初始输入后经常不更新数据,这会降低不一致的风险。
但一般来说,为了性能而对非规范化感到厌倦。例如,非规范化连接的性能优势通常可以通过使用物化视图(也称为索引视图)来实现,这将与查询非规范化表一样快,但是仍然保护数据的一致性。
【讨论】:
【参考方案4】:Jeff 在他的博客上对他的哲学有一个很好的概述:Maybe normalization isn't normal。最主要的是:不要过度标准化。但我认为更重要的一点是,它可能并不重要。除非您正在运行下一个 Google,否则在您的应用程序增长之前,您可能不会注意到太大的差异。
【讨论】:
您绝对会注意到数据库中是否有冗余数据!这意味着您要么必须重写更新以在多个位置更新相同的数据,要么获得不一致的数据。这与应用程序的大小无关,这是将相同数据存储在多个位置的逻辑结果。【参考方案5】:我觉得数据库规范化是一种艺术形式。
您不希望过度规范化您的数据库,因为您将拥有太多的表,这会导致您对即使是简单对象的查询也花费比应有的更长的时间。
我遵循的一个很好的经验法则是将一遍又一遍地重复的相同信息标准化。
例如,如果您正在创建一个联系人管理应用程序,那么将 Address(Street、City、State、Zip 等)作为自己的表是有意义的。
但是,如果您只有 2 种类型的联系人,企业或个人,如果您知道您只有 2 种联系人类型表,您是否需要一个联系人类型表?对我来说没有。
我会首先找出您需要的数据类型。使用建模程序来帮助像 Visio。您不想从非规范化数据库开始,因为您最终会规范化。首先将对象放入逻辑分组中,因为您看到重复的数据将这些数据放入新表中。我会跟上这个过程,直到你觉得你已经设计好了数据库。
让测试告诉您是否需要合并表格。编写良好的查询可以涵盖任何过度规范化。
【讨论】:
-1 “我遵循的一个好的经验法则是将一遍又一遍地重复的相同信息标准化”——您似乎打算将***重新发明为方形!这里有很多废话,例如“你不想从非规范化的数据库开始,因为你最终会规范化。” 在同一个表中有两个地址与非规范化无关。应该妥协什么正常形式?【参考方案6】:我相信从一个未规范化的数据库开始,随着你的进步逐渐走向规范化通常是最容易开始的。对于正常化到何种程度的问题,我的理念是正常化直到开始受到伤害。这听起来可能有点轻率,但通常是衡量要走多远的好方法。
【讨论】:
未规范化的数据库根据定义是具有冗余和/或不一致数据的数据库。如果你想从一个未规范化的数据库转到一个规范化的数据库,你需要一个过程来清理和消除这些冗余数据。这比一开始就设计规范化的数据库并完全避免不一致的数据要容易得多吗?【参考方案7】:拥有一个规范化的数据库将为您提供最大的灵活性和最简单的维护。我总是从规范化的数据库开始,然后仅在存在需要解决的现实问题时才取消规范化。
我认为这类似于代码性能,即编写可维护、灵活的代码并在您知道存在性能问题时为性能做出妥协。
【讨论】:
【参考方案8】:原始发帖人从未描述数据库将在什么情况下使用。如果它将是任何类型的数据仓库项目,在某些时候您将需要多维数据集 (OLAP) 为某些前端处理数据,那么从星型模式(事实表 + 维度)开始而不是调查会更明智正常化。在这种情况下,Kimball 书籍将有很大帮助。
【讨论】:
【参考方案9】:我同意从规范化 DB 开始,然后进行非规范化以解决非常具体的问题通常会更好,但我可能会从 Boyce-Codd Normal Form 开始,而不是第 3 范式。
【讨论】:
【参考方案10】:事实是“视情况而定”。这取决于很多因素,包括:
代码(手动编码或工具驱动(如 ETL 包)) 主要应用程序(事务处理、数据仓库、报告) 数据库类型(mysql、DB/2、Oracle、Netezza 等) 数据库架构(表格、列) DBA 质量(主动、被动、非主动) 预期的数据质量(您想在应用程序级别还是数据库级别强制执行数据质量?)【讨论】:
【参考方案11】:我同意您应该尽可能地进行规范化,并且仅在性能绝对必要时才进行非规范化。而对于物化视图或缓存方案,这通常是不必要的。
要记住的是,通过规范化您的模型,您可以为数据库提供有关如何约束数据的更多信息,这样您就可以消除在不完全规范化的模型中可能发生的更新异常的风险。
如果您进行非规范化,那么您要么需要忍受可能会出现更新异常的事实,要么您需要自己在应用程序代码中实现约束验证。这会带走使用 DBMS 的许多好处,因为 DBMS 允许您以声明方式定义这些约束。
因此,假设代码质量相同,非规范化实际上可能不会给您带来更好的性能。
另外需要提及的是,如今硬件很便宜,因此在问题上投入额外的处理能力通常比接受清理损坏数据的潜在成本更具成本效益。
【讨论】:
【参考方案12】:通常,如果您在其他软件允许的范围内进行标准化,那么您就完成了。
例如,当使用对象-关系映射技术时,您将拥有一组丰富的语义,用于各种多对一和多对多关系。在引擎盖下,它将为连接表提供有效的 2 个主键。虽然相对罕见,但真正的规范化通常会为您提供与 3 个或更多主键的关系。在这种情况下,我更喜欢坚持使用 O/R 并滚动我自己的代码以避免各种数据库异常。
【讨论】:
规范化不规定任何数量的键。它讨论了候选键,但如果您更喜欢单个 id,您始终可以创建代理键。【参考方案13】:尝试使用常识。
还有人说 - 我必须同意他们 - 如果您发现自己在大多数查询中将 6 个(幻数)表连接在一起 - 不包括报告相关的表 - ,那么您可能会考虑非规范化有点。
【讨论】:
如果您的连接变得复杂,您应该考虑引入一些视图来简化查询。另一方面,非规范化意味着引入冗余数据,这只会让一切变得更加复杂。以上是关于您如何确定数据库规范化的程度?的主要内容,如果未能解决你的问题,请参考以下文章