什么时候应该规范化?


45

我认为我们都熟悉数据库规范化

我的问题是:要对表格进行非规范化时,使用哪些准则?


3
与Internet上的其他站点相比,StackExchange网站具有一个独特的优势,即:1)它们使最佳答案变得最容易找到; 2)最佳答案由社区确定。正因为如此,我认为,这个网站和互联网将受益于这个问题,尽管它那种违背了常见问题
理查德


Answers:


34

在进行OLAP操作时进行归一化,在进行OLTP时进行归一化(来自“归一化”部分下的链接文章)

通常,用于联机事务处理(OLTP)的数据库比用于联机分析处理(OLAP)的数据库规范化得多。OLTP应用程序的特点是大量的小额交易,例如在超市结帐柜台更新销售记录。期望每个事务将使数据库保持一致状态。相比之下,用于OLAP操作的数据库主要是“多数读取”数据库。OLAP应用程序倾向于提取长期积累的历史数据。对于此类数据库,冗余或“非规范化”数据可以促进商业智能应用程序。具体来说,星型架构中的维表通常包含非规范化数据。在提取,转换,加载(ETL)处理期间,必须对非规范化或冗余数据进行仔细控制,并且除非数据处于一致状态,否则不允许用户查看该数据。星形模式的规范化替代方案是雪花模式。在许多情况下,随着计算机和RDBMS软件变得越来越强大,对非规范化的需求已经减弱,但是由于数据量通常随着硬件和软件性能的增加而增加,因此OLAP数据库通常仍使用非规范化架构。

非规范化还用于提高小型计算机(如计算机化的现金出纳机和移动设备)上的性能,因为它们可能会将数据仅用于查找(例如,价格查找)。当针对平台(例如Palm)的RDBMS不存在,或者不对数据进行任何更改并且快速响应至关重要时,也可以使用非规范化。


4
在创建报告或分析时,我需要进行非规范化处理,并希望获得快速的结果。世界上所有具有多个联接的索引从来没有像表示将不会更改的缓存数据的非规范化表那样快。
kevinsky

简洁,非常有帮助。我一直在研究DBA的外围功能,这有助于使很多事情变得完整。
杰森·萨林格

许多应用程序同时具有OLAP和OLTP要求,因此每个后端开发人员都应该学习如何混合使用这两个要求以及如何使非规范化数据保持最新。
JustAMartin

22

归一化直到痛苦,反归一化直到起作用(即:性能可以接受):)


5
这可能不是最佳答案,但它是我在Stack Overflow上看到的最好的单行代码之一:)
Owen

15

应用受控的非规范化的一个可能合理的原因是,它是否使您能够对数据应用某些完整性约束,否则将无法实现这些约束。大多数SQL DBMS对多表约束的支持极为有限。在SQL中,有时实现特定约束的唯一有效方法是确保约束所涉及的属性都存在于同一表中,即使规范化要求它们属于不同的表也是如此。

受控非规范化意味着实施机制以确保不会由于冗余数据而出现不一致。在确定是否值得进行非规范化时,需要考虑这些额外控件的成本以及数据不一致的风险。

进行非规范化的另一个常见原因是允许对存储结构进行一些更改,或者允许进行DBMS不允许的其他一些物理优化。根据物理数据独立性原则,DBMS应该具有配置内部存储结构的方法,而不必不必要地更改数据库中数据的逻辑表示。不幸的是,许多DBMS严重限制了任何给定数据库模式可用的物理实现选项。它们往往仅通过支持所需逻辑模型的次优实现而损害物理数据库的独立性。

它应该很明显,但仍然需要说:在所有情况下,只有物理实现功能的变化才可以决定性能-这些功能包括内部数据结构,文件,索引,硬件等。规范化和非规范化与性能或存储优化无关。


4

如果您经常访问计算数据,请进行规范化处理,如该问题的答案所示。如果负载配置文件读取繁重,则存储和维护计算数据的成本通常会比一遍又一遍地重新计算数据的成本低。


请注意,如果非规范化只是为了缓存值,则这特别有用。因此,仍然存在表/字段的基础归一化集合。也就是说,对于每个值,应该有一个保存该值的“主”单元-已知其他值仅仅是该主单元的副本或计算-除非这样做有很大好处,否则请保留所有主单元在正常的关系中。
ToolmakerSteve

3

我通常会进行非规范化,以便可以在有约束的情况下强制执行数据完整性。一个示例是该站点上最近出现的一个问题 -我将一列复制到另一个表中,以便可以使用CHECK约束将其与另一列进行比较。这种技术的另一个示例是我的博客文章

您不能使用CHECK约束比较不同行或不同表中的列,除非您将此类功能包装在从CHECK约束调用的标量UDF中。如果您实际上需要比较不同行或不同表中的列以实施业务规则怎么办?例如,假设您知道医生的工作时间,并且想要确保所有约会都适合工作时间?当然,您可以使用触发器或存储过程来实现此业务规则,但是无论是触发器还是存储过程都不能100%保证您的所有数据都是干净的–有人可以禁用或删除触发器,请输入一些脏数据,然后重新启用或重新创建触发器。也有人可以绕过存储过程直接修改您的表。

让我演示如何仅使用FK和CHECK约束来实现此业务规则-这将确保只要所有约束均受信任,所有数据都将满足业务规则。

另一个例子是一种强制时间段没有间隙和重叠的方法


1
“我通常会进行非规范化,以便可以在约束条件下强制执行数据完整性。” 同样在这里。这是一个很大的权衡:您可以稍微规范化一下,但可以获得DRI
Nick Chammas 2012年

@NickChammas-这非常有趣。做这些事情时,您可以分享方案吗?
AK 2012年

1
当然。我们有一个实现系统,其中包括要执行的项目队列。有一个Fulfillable表包含每个Fulfillable项的所有详细信息,然后有一个FulfillableQueue在SQL Server中实现队列StateID队列中只有特定的可实现对象。StateIDFulfillable表中,但我将其复制到FulfillableQueue,然后使用FOREIGN KEYCHECK约束强制执行此约束。
Nick Chammas 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.