我是否应该规范我的数据库?

问题描述 投票:32回答:9

[为数据库(例如MySQL)设计模式时,是否要完全规范化表就出现了问题。

一方面,联接(和外键约束等)非常慢,另一方面,您获得了冗余数据,并可能导致不一致。

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

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

该数据库将被大量插入的事实影响该决定吗?

mysql database optimization rdbms database-normalization
9个回答
32
投票

哲学上的答案:次优(关系)数据库中充斥着插入,更新和删除异常。这些都会导致数据不一致,从而导致数据质量较差。如果您不相信数据的准确性,那有什么好处?问问自己:您想要正确答案的速度变慢还是想要错误答案的速度变快?

实际情况:在快速掌握之前,先弄好它。我们人类很难预测瓶颈将在何处发生。使数据库更好,在相当长的一段时间内评估性能,然后确定是否需要使其更快。在取消规范化和牺牲准确性之前,请尝试其他技术:您可以获得更快的服务器,连接,数据库驱动程序等吗?存储过程可能会加快速度吗?索引及其填充因子如何?如果这些以及其他性能和调整技术无法解决问题,请仅考虑非规范化。然后测量性能以验证您是否获得了“付费”速度的提高。确保您正在执行优化,而不是悲观。

[编辑]

问:如果我最后进行优化,建议合理的迁移方式模式更改后的数据?如果,例如,我决定摆脱查找表-如何迁移现有数据库存储到此新设计中?

A:好的。

  1. 进行备份。
  2. 将另一个备份保存到其他设备。
  3. 使用“从oldtable中选择到新表中...”类型的命令来创建新表。您需要进行一些联接以合并以前不同的表。
  4. 丢弃旧表。
  5. 重命名新表。

BUT ...考虑一种更可靠的方法:

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

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


14
投票

您数据库的使用模式(大量插入与大量报告)肯定会影响您的规范化。此外,如果看到标准化表的速度显着下降,则可能需要查看索引等。您正在使用哪个版本的MySQL?

通常,与报告繁重的数据库相比,对插件繁重的数据库应进行标准化。但是,YMMV当然......>

正常的设计是开始的地方;首先,要使其正确,因为您可能不需要使其快速。

对时间花费很大的连接的担心通常是基于不良设计的经验。随着设计变得更加正常,设计中的表数通常会增加,而每个表中的列数和行数会减少,设计中的并集数会随着连接数的减少而增加,索引会变得更加有用。换句话说:好事发生了。

并且规范化只是以常规设计结束的一种方法...

您从哪里得知“联接(以及外键约束等)非常慢”?这是一个非常含糊的声明,通常IMO没有性能问题。

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

不要过早地使用非规范化数据优化数据库。这是解决持续的数据完整性问题的良方。另外,请始终使用数据库触发器来管理非规范化的数据-不要依赖应用程序来执行此操作。

最后,如果需要提高报告性能,请考虑构建数据集市或其他单独的非规范化结构来进行报告。结合了对实时数据的实时视图要求的报告很少,而且往往只在少数几条业务线中出现。可以做到这一点的系统往往很容易构建,因此很昂贵。

几乎几乎可以肯定,只有少量报告真正需要最新数据,而它们几乎总是像待办事项列表这样的操作报告,或者处理少量数据的异常报告。可以将其他任何内容推送到数据集市,而每晚刷新可能就足够了。

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

我会说,是的。我不得不处理结构不良的数据库太多次,以至于没有太多思想就纵容“平表”数据库。

实际上,插入通常在完全标准化的DB上表现良好,因此,如果插入很重,这不应该是一个因素。

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

仅当这无济于事时,您应该尝试对表格进行非规范化。请确保在非规范化之前和之后对插入和查询进行基准测试,因为这很可能会降低插入速度。

此问题的一般设计方法是,首先将数据库完全规范化为第三范式,然后根据需要对规范进行非规范化,以提高性能并简化访问。这种方法往往是最安全的,因为您是通过设计做出特定决策,而不是默认情况下不进行标准化。

“适当时”是需要经验的技巧。规范化是一个相当“循序渐进”的过程,可以教,知道在哪里进行非规范化不太精确,并且将取决于应用程序的使用情况和业务规则,因此每个应用程序之间都会有所不同。您所做的所有非规范化决策都应该对专业人士具有防御力。

例如,如果我有一对多的关系,那么从A到BI的关系在大多数情况下将归一化,但是如果我知道企业仅对每个A发生两次B的事件,那么更改,B记录中的数据有限。他们通常会使用A记录来回退B数据,我很可能会通过两次出现B字段来扩展A记录。当然,大多数通过的DBA都会立即将其标记为可能的设计问题,因此您必须能够令人信服地提出反规范化的理由。

由此可见,非规范化应该是例外。在任何生产数据库中,我都希望其中的绝大多数-95%以上-处于第三范式,只有少数非规范化结构。

我不知道您对创建数据库的含义

by-the-book

,因为我读过的大多数关于数据库的书都包含有关优化的主题,这与对数据库设计进行非规范化是一样的事情。
这是一种平衡行为,因此请不要过早优化。原因是非规范化的数据库设计往往难以使用。您将需要一些指标,因此需要对数据库进行一些压力测试,以便确定是否要进行非规范化。

因此,为了可维护性而标准化,但为了优化而去标准化。


8
投票
正常的设计是开始的地方;首先,要使其正确,因为您可能不需要使其快速。

5
投票
您从哪里得知“联接(以及外键约束等)非常慢”?这是一个非常含糊的声明,通常IMO没有性能问题。

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

4
投票
这里“最优化”是正确的方法吗?即创建一个按书归一化的数据库,然后查看可以进行归一化以实现最佳速度增益的内容。

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

4
投票
此问题的一般设计方法是,首先将数据库完全规范化为第三范式,然后根据需要对规范进行非规范化,以提高性能并简化访问。这种方法往往是最安全的,因为您是通过设计做出特定决策,而不是默认情况下不进行标准化。

3
投票
我不知道您对创建数据库的含义

by-the-book

© www.soinside.com 2019 - 2024. All rights reserved.