我正在处理一个大型项目,该项目有许多表示简单(不相关)值的对象。这些值有时是单个字符串,有时是两个字符串,有时是一个字符串和一个整型…
目前,我们在关系数据库中有一个'values'表,其中包含以下列:Id
, Category
, String1
, String2
…, Int1
, Int2
…Double1
等。这很方便,但是很乱。
这些值都有以下属性:
- 具有相同
Category
的每个对象具有相同的属性(即。类型)。 - 没有对象相关(唯一的键是
Id
主键)。
我们如何走出这个混乱?在我看来,我们的选项如下:
- 只要继续添加必要的列,忘记表和对象之间的语义映射。
- 为每个值对象创建一个新表。这将向数据库中添加大量表,其中大多数表的行数少于6行。我担心所有这些额外的表添加到数据库中的噪音。
- 为这些对象部署一个无模式数据库(在我们的部署场景中不太可能)。
- 创建一个包含
Id
、Category
列和Value
列的BLOB表,并将值对象序列化到值列中。这可行吗?
这篇文章重申了我们的选择。使用序列化有什么警告或缺陷吗?还有我不知道的选择吗?欢迎指教
我在浏览另一个相关问题时偶然发现了这个问题。虽然这个问题相当古老,但我还是很想回答,因为它不仅提出了一个非常明确的问题,而且还允许人们从整体上讨论数据库反规范化。
有很多原因,甚至更多的理由使数据库非规范化。性能可能是最重要的,但数据分类困难(比如手头的问题)绝对是最常见的。此外,有许多方法可以使数据库非规范化,其中许多方法由op解决。
然而,事实是,在失败之后,数据库的应该被反规范化为作为最后的手段。原因包括:数据变得毫无意义对于人类以及RDBMS。对于某些人来说,理解甚至记住一个名为
Integer1
的字段或一个可能包含任何内容的序列化值的目的是很困难的。RDBMS不能从序列化的实体中提取值,以便对结果进行排序或应用聚合。维护volatile模式是困难的。数据库模式应该是常量是有原因的。其他更高的水平依赖于它。如果模式一夜之间改变了,应用程序也应该改变,以反映新的状态。更糟糕的是,视图、存储过程和其他依赖数据库的组件变得同样难以维护。
不能强制约束,不能创建索引。将序列化字段定义为外键或将其限制为特定的一组值是没有意义的。这取消了大量数据库的自我保护机制。更少的数据完整性意味着更多的管理成本。此外,索引在这里同样是无用的,使表更不容易进行优化。
元数据最终必须存储为数据。想象一个多语言CMS,其中有一个主
article
表来保存文章。现在,对于每种支持的语言,都有一个相应的article_{lang}
表来保存翻译(即article_en
,article_fr
,article_es
等)。为了记录文章的现有翻译,应该创建一个"关系"表,其中包含article
表的外键、语言id、翻译表的表名和一个字段,该字段应该是翻译表的FK,但不能定义为一个。然后,尝试编写一个查询,统计每篇文章的可用翻译!
因此尽可能避免非规范化。如果实体可以在一定程度上分类,那么IS-A关系可能是答案。为了支持任意属性,或者当不值得进行分类时,一个键/值对表,加上一个存放规范化数据的表的外键,就足够了。