【问题标题】:Should I normalize my DB or not?我应该标准化我的数据库吗?
【发布时间】:2010-10-30 09:25:51
【问题描述】:

在为数据库(例如 MySQL)设计架构时,会出现是否完全规范化表的问题。

一方面连接(和外键约束等)非常慢,另一方面你会得到冗余数据和潜在的不一致。

“最后优化”是正确的方法吗?即创建一个按规范规范化的数据库,然后查看可以进行非规范化以实现最佳速度增益。

对于这种方法,我担心的是我会选择一个可能不够快的数据库设计 - 但在那个阶段重构架构(同时支持现有数据)会非常痛苦。这就是为什么我很想暂时忘记我学到的关于“正确”RDBMS 实践的所有内容,并尝试一次“平面表”方法。

这个数据库将是插入重的事实是否会影响决策?

【问题讨论】:

  • 你在谈论什么应用程序会产生很大的不同。是企业价格/业务逻辑还是公共网站或其他什么?
  • @Bogdan,这是一个跟踪许多具有地理位置的对象的系统。
  • 好吧,你们基本上把我吓坏了,直接回到第 5 规范化形式。那谢谢啦。不过,阅读答案仍然很有趣。
  • BCNF 应该没问题。如果您基于正确的函数依赖进行分解并且您的 PK-FK 关系缺少传递依赖,那么您可能会通过 3NF 免费获得它。
  • 4NF 和 5NF 仅对 M:M 关系感兴趣。

标签: mysql database optimization rdbms database-normalization


【解决方案1】:

您的数据库的使用模式(插入重与报告重)肯定会影响您的规范化。此外,如果您发现规范化表显着放缓,您可能需要查看索引等。您使用的是哪个版本的 MySQL?

一般来说,插入繁重的数据库应该比报告繁重的数据库更多标准化。不过,YMMV 当然是……

【讨论】:

  • 使用 5.1。您能否详细说明为什么需要对插入繁重的数据库进行更多规范化? YMMV?
  • 插入重的数据库应该更加规范化,因为它们的主要重点是捕获数据。如果它是事务性的,您需要一个 3NF 数据库。如果您正在做一个主要关注提取信息的报告数据库,那么您需要一个半非规范化的数据库。
  • "YMMV" = "您的里程可能会有所不同",如汽车报告的燃油里程。换句话说,对于特定情况,您可能不会得到完全相同的结果。
  • 更一般地说,规范化数据库从数据中取出数据的速度较慢(因为必须计算更多),但将数据输入更快(因为必须做的更少)。因此,插入量大的数据库将受益于规范化,但数据仓库数据库将受益于较少的规范化。
【解决方案2】:

“最后优化”是正确的方法吗?即创建一个按规范规范化的数据库,然后查看可以进行非规范化以实现最佳速度增益。

我会说,是的。我不得不处理结构糟糕的数据库太多次,无法在没有经过深思熟虑的情况下容忍“平面表”数据库。

实际上,插入通常在完全规范化的数据库上表现良好,所以如果插入很重,这不应该是一个因素。

【讨论】:

    【解决方案3】:

    一个哲学答案:次优(关系)数据库充斥着插入、更新和删除异常。这些都导致数据不一致,导致数据质量不佳。如果你不能相信你的数据的准确性,那有什么好处呢?问问自己这个问题:您想要更慢地得到正确答案还是想要更快地得到错误答案?

    作为一个实际问题:在快速完成之前先把它做好。我们人类非常不擅长预测瓶颈会发生在哪里。让数据库变得更好,在相当长的一段时间内衡量性能,然后决定是否需要让它更快。在你去规范化和牺牲准确性之前尝试其他技术:你能获得更快的服务器、连接、数据库驱动程序等吗?存储过程会加快速度吗?索引及其填充因子如何?如果这些以及其他性能和调优技术不能解决问题,那么只有考虑非规范化。然后测量性能以验证您是否获得了“付费”的速度提升。确保您正在执行优化,而不是悲观化。

    [编辑]

    问:所以如果我最后优化,你能 推荐合理的迁移方式 架构更改后的数据?如果, 例如,我决定摆脱一个 查找表 - 我如何迁移 现有数据库到这个新设计?

    答:当然。

    1. 进行备份。
    2. 再次备份到其他设备。
    3. 使用“select into newtable from oldtable...”类型命令创建新表。您需要进行一些连接来组合以前不同的表。
    4. 删除旧表。
    5. 重命名新表。

    但是...考虑一种更稳健的方法:

    立即在完全规范化的表上创建一些视图。这些视图(虚拟表、数据上的“窗口”......问我是否想了解更多关于该主题的信息)将具有与上述第三步相同的定义查询。当您编写应用程序或 DB 层逻辑时,请使用视图(至少用于读取访问;可更新的视图......嗯,很有趣)。然后,如果您稍后进行非规范化,则如上所述创建一个新表,删除视图,重命名新的基表,无论视图是什么。您的应用程序/数据库层不会知道其中的区别。

    在实践中实际上还有更多内容,但这应该可以帮助您入门。

    【讨论】:

    • 那么如果我最后优化的话,能否推荐一个合理的方式在架构改变后迁移数据?例如,如果我决定摆脱查找表 - 我如何将现有的数据库迁移到这个新设计?
    • 如果您使用的是 SQL Server,请查找“Instead Of”触发器。这是我最喜欢的触发器。
    【解决方案4】:

    此问题的一般设计方法是首先将您的数据库完全规范化为第 3 范式,然后根据性能和易用性进行适当的反规范化。这种方法往往是最安全的,因为您是通过设计做出具体决定,而不是默认不规范化。

    “适当”是需要经验的棘手部分。规范化是一个可以教授的相当“死记硬背”的过程,知道在哪里进行非规范化不太精确,并且取决于应用程序的使用和业务规则,因此会因应用程序而异。您所有的非规范化决定都应该在专业同行中得到辩护。

    例如,如果我有一对多的关系,将 A 发送到 BI,在大多数情况下,这会使其正常化,但如果我知道该业务只存在,例如,每个 A 出现两次 B,那么这极不可能要更改,B 记录中的数据有限。他们通常会用 A 记录拉回 B 数据,我很可能会用两次出现的 B 字段来扩展 A 记录。当然,大多数通过 DBA 的人会立即将其标记为可能的设计问题,因此您必须能够令人信服地论证您对非规范化的理由。

    很明显,非规范化应该是例外。在任何生产数据库中,我预计其中的绝大多数(95% 以上)都处于第三范式,只有少数非规范化结构。

    【讨论】:

      【解决方案5】:

      在插入量很大的数据库上,我肯定会从规范化表开始。如果您对查询有性能问题,我会首先尝试优化查询并添加有用的索引。

      只有当这没有帮助时,您才应该尝试非规范化表。请务必在非规范化之前和之后对插入和查询进行基准测试,因为您可能会减慢插入速度。

      【讨论】:

        【解决方案6】:

        您从哪里得到“连接(和外键约束等)非常慢”的想法?这是一个非常模糊的陈述,通常 IMO 没有性能问题。

        【讨论】:

        • 加入不是免费的。根据您的数据库的规范化程度,您可能会以一个数量级查看慢得多的查询。从本质上讲,它是每个表的所有行的叉积,其中不满足连接条件的行将被消除。这可能已经过优化,但这仍然是一项成本更高的操作。
        • @Assaf:OTOH,您的数据可能较少,因此数据适合 RAM。你声称“本质上它是一个交叉产品......”是完全错误的。这是一个连接,仅此而已。
        • 扫描好的索引,尤其是覆盖索引的连接性能非常好。另一件事是锁定你的桌子。根据您的要求,拥有多个表可能意味着某些插入、删除和更新可以安全地同时发生在不同的表中。
        【解决方案7】:

        在操作系统上很少需要非规范化。我为其创建数据模型的一个系统有 560 个左右的表(当时它是澳大利亚最大的 J2EE 系统),并且只有 4 条非规范化数据。其中两个项目是非规范化的搜索表,旨在促进复杂的搜索屏幕(一个是物化视图),另外两个是为了响应特定的性能要求而添加的。

        不要使用非规范化数据过早地优化数据库。这是持续的数据完整性问题的秘诀。此外,始终使用数据库触发器来管理非规范化数据 - 不要依赖应用程序来做。

        最后,如果您需要提高报告性能,请考虑构建数据集市或其他单独的非规范化报告结构。结合对大量数据计算的聚合的实时视图的要求的报告很少见,而且往往只出现在少数业务线中。可以做到这一点的系统往往很难构建,因此价格昂贵。

        您几乎可以肯定只有少量真正需要最新数据的报告,而且它们几乎总是操作性报告,如待办事项列表或处理少量数据的异常报告。其他任何东西都可以推送到数据集市,为此,每晚刷新一次可能就足够了。

        【讨论】:

          【解决方案8】:

          我不知道你对创建数据库的意思是什么按本书,因为我读过的大多数关于数据库的书籍都包含一个关于优化的主题,这与非规范化数据库相同设计。

          这是一种平衡行为,因此不要过早优化。原因是非规范化的数据库设计往往变得难以使用。您需要一些指标,因此对数据库进行一些压力测试,以确定是否要进行非规范化。

          所以为了可维护性进行规范化,但为了优化而去规范化。

          【讨论】:

            【解决方案9】:

            正常的设计是开始的地方;首先要把它做对,因为你可能不需要让它很快。

            对耗时的连接的担忧通常是基于糟糕设计的经验。随着设计变得更加正常,设计中的表数通常会增加,而每个表中的列数和行数会减少,设计中的联合数会随着连接数的减少而增加,索引变得更有用等等。换句话说:好事发生。

            而规范化只是实现正常设计的一种方式...

            【讨论】:

              猜你喜欢
              • 2021-10-29
              • 2019-07-31
              • 1970-01-01
              • 2020-05-08
              • 2021-05-28
              • 2017-07-05
              • 1970-01-01
              • 2020-01-10
              • 2023-03-10
              相关资源
              最近更新 更多