何时是打破规范化规则的好时机?

时间:2010-01-14 15:33:41

标签: database-design normalization

请对不合规的情况提出自己的看法。我刚刚目睹了一个架构师和DBA之间激烈的讨论,他们坚持认为数据库是TOO标准化的。

10 个答案:

答案 0 :(得分:11)

性能查询可能性:如果数据库过于规范化,这可能会导致查询中出现大量连接,并限制了搜索特定属性的可能性。 在进行数据库设计时,您应该通过访问路径分析来考虑计划使用它的方式。

详细说明,规范化经常更新的数据并对主要读取的数据进行非规范化是一个经验法则。

答案 1 :(得分:10)

规则正常化直到它受伤,然后非规范化直到它起作用。 (谁说的?)

一般情况下,当我有很多父子关系时,我经常会反规范化,而且我知道我经常需要加入五到六个大表来获取一个数据(例如客户端ID)并且不会在很多时候需要来自中间表的任何信息。如果可能的话,我会尝试对不会经常更改的内容(例如id字段)进行非规范化。但是无论何时你进行非规范化,你都必须编写触发器或其他一些进程(但是如果它不是可以通过PK / FK关系和级联更新来处理的话,通常会触发)以确保数据保持同步。如果您未能在数据库级别执行此操作,则会出现数据完整性问题,并且您的数据将变得无用。不要以为您可以通过应用程序代码维护非规范化。这是一个灾难的处方,因为数据库经常从应用程序以外的地方更新。

正确地进行非规范化会降低插入,更新和删除的速度,尤其是在需要执行大批量数据时。它可能会也可能不会提高选择查询速度,具体取决于您查询数据的方式。如果您最终需要进行大量的自连接来获取数据,那么最好不要进行非规范化。永远不要在没有测试的情况下进行非规范化,看看你是否有改进记住,当许多用户使用它时,减慢插入/更新/删除将对系统产生整体影响。通过非规范化来解决一个问题,您可能会在整个系统中引入更严重的问题。不要只测试你试图加速的一个查询,测试整个系统的性能。您可以加快每月运行一次的查询速度,并减慢每天运行数千次的其他qreries。

通常对数据仓库进行非规范化,这是特殊情况,因为它们通常按计划自动更新,而不是由用户一次更新一个记录。专门从事数据仓库的DBA也倾向于构建它们,并且知道如何避免数据完整性问题。

另一种常见的非规范化技术是为与复杂报表相关的数据创建一个临时表,该报表不需要使用实时数据运行。这是一种穷人的数据仓库,如果没有按计划更新登台表的方法,就不应该这样做(尽管你可以随意使用,但这会使用服务器资源,这些资源可能会在大多数时间更好地花费在其他地方。 )当系统上的用户很少并且落后于实时数据一整天时,通常会更新这些类型的表。不要考虑这样做,除非您正在暂存数据的查询真的很慢,否则无法进行优化。许多慢速查询可以在没有反复异化的情况下进行优化,因为开发人员通常使用最简单的方法来理解,而不是以最高效的方式来选择数据。

答案 2 :(得分:6)

当你过早优化时

有些规范化可以让未来增长,而你可能不需要它。

例如,假设您有一个person表。您可以将birthday作为列,因为每个人只有一个生日。

如果您严格规范化,则phone_number中不会有cell_numberfax_numberperson作为列,但可能会有phonenumber } table其中每一行都有一个数字,一个类型和一个person_id关系。这可能比在person表中添加新列更好,因为

  1. 许多人不会拥有所有这些,留下大量空白,
  2. 如果有人有3个单元格编号,则会添加cell_number_2
  3. 等笨拙的列

    关注#1是有效的,但关注#2可能是“你不需要它”的一个例子。说“我们只允许一个细胞数,这就是那个”是有效的。在这种情况下,您可能不会为电话号码制作单独的表格。

    这是一个权衡。通过不创建单独的表,您不是严格规范化,并且您可能有很多NULL空格。但是你也可以减少连接次数,而且工作量也会减少。

    与许多良好实践一样,规范化本身可以成为目的 - 您私下给自己的金徽章,因为您做得对。那没关系。 但很高兴认识到,为了保持简单,有时可以修改规则。

    最后一件事:一旦代码启动并运行,您必须权衡更改db模式的事实。所以可以说“我们不需要它”,但在你提交之前尽量确定。

答案 3 :(得分:5)

已经有几个关于存储与性能的好答案,但另外我还要添加一个块,这对我来说应该考虑去规范化是你需要使用自连接查询的地方。

从概念上讲,自联系表没有任何问题,但经验表明,对于没有经验的程序员来说,这是一个比较困难的概念,因此容易产生错误。如果你可以设计出这些需求,你很可能会放松未来的维护路径。

这当然是判断问题,因此是一种指示,而非规则。

答案 4 :(得分:2)

你必须找到最佳点...过于规范化,你最终会得到很多“臃肿”的抽象结构,它们只包含1或2列数据,你最终会加入5个表来进行大多数查询。

由于规范不足,您最终会在很多不同的地方拥有大量数据。由于缓存大小等原因,这可能导致DB变慢。此外,现在当你需要更新某些东西时,你有4个不同的表来更新而不是1,甚至不让我开始确保不同地方的所有数据都匹配!

基本上,选择你的毒药,看看你的数据库将如何使用,并保持理智。所有的规则都打算被破坏,如果你有2个地方的数据通常被访问,我会说没关系。这是一个关键的部分,连接(可能超过2个)表可能太昂贵..但也不要微量优化数据库的空间或速度。

答案 5 :(得分:2)

在他们正常化的地方工作。他们从邮寄地址表中删除了“州”列。代替2字节状态列,它们将整数外键字段链接到状态表。

总结:

  • 他们用地址中的4字节列替换了一个2字节的状态列 表。现在每行需要2个字节的存储空间。

  • 他们添加了一个状态表,其中包含一个4字节的主键列和一个2字节的状态列。占用更多空间来存储此表。

  • 数据库在状态表中保留键的btree索引。占用更多空间。

  • 用于检索地址的sql更难写。

  • 检索地址的sql比原始地址慢。

当然,这天真地删除了重复的不变数据。结果是它使用了更多的磁盘空间,使用起来更加困难,并且使用起来更慢。

你绝对可以规范化太多。

答案 6 :(得分:1)

规范化消除了冗余,但如果它以某种方式降低性能(由于所有必需的连接),则硬件成本不足,是时候为了性能而允许冗余。这是我的经验法则。在答案时间较长的情况下也是如此。

答案 7 :(得分:1)

出于性能原因,数据仓库通常使用非规范化方法。每wikipedia

  

标准的数据库设计指导是设计师应该创建一个完全标准化的设计;随后可出于性能原因执行选择性非规范化。但是,一些建模学科,如数据仓库设计的维度建模方法,明确推荐非标准化设计,即大部分不符合3NF的设计。

答案 8 :(得分:0)

报告和数据仓库可能是您发现数据非规范化的最大位置。 OLAP系统通常总是非规范化为单个表或一组表。

答案 9 :(得分:0)

当您遵循导致模式不完全规范化的设计规则时,请不要规范化。一个这样的设计学科是星型模式设计,它的一个紧密变体是雪花模式。

星型和雪花都将产生一种模式,该模式更易于用于各种报告,自定义提取以及与诸如Cognos Power Play等OLAP工具的接口。不足之处?每次偏离正常形式之一(1NF除外)在插入/更新/删除数据时都会带有异常。如果你真的知道正常形式,你就会知道相关的异常是什么。当您编写ETL(提取,转换和加载)程序以保持星形/雪花最新时,您将不得不解决这些异常现象。

那么星形或雪花模式何时比标准化模式更好?通常,用于数据仓库,数据集市和报告数据库。在我自己的实践中,我从来没有构建其中一个不是OLTP数据库的后端,并且OLPT数据库受益于几乎完全的规范化。不要只是反规范化并放弃所有纪律。这就像是随意设计。