我正在处理一个包含许多表示简单(非相关)值的对象的大型项目。有时这些值是单个字符串,有时它们是两个字符串,有时是字符串和int ...
目前,我们的关系数据库中有一个“值”表,其中包含以下列:Id
,Category
,String1
,String2
...,{{1 }},Int1
...,Int2
等。这很方便,但很乱。
这些值都具有以下属性:
Double1
的每个对象具有相同的属性(即输入)。Category
主键)。我们如何摆脱这个烂摊子?我认为,我们的选择如下:
Id
,Id
列和BLOB Category
列的表,并将值对象序列化到值列中。这可行吗?This post重申了我们的选择。使用序列化有任何警告或陷阱吗?有没有我不知道的选择?建议最受欢迎。
答案 0 :(得分:2)
我从another relevant question导航,偶然发现了这一点。虽然它已经很老了,但我很有兴趣回答,因为它不仅提出了一个非常明确的问题,而且还允许人们对数据库非规范化作为一个整体进行论证。
对于数据库进行非规范化,有很多原因甚至更多借口。性能可能是最重要的,但数据分类的难度(例如手头的问题)绝对是最常见的。此外,有很多种方式数据库可以非规范化,并且OP可以解决大量的数据库问题。
事实上,数据库应该被归一化为万不得已,其他一切都失败后。原因包括:
数据对人类和RDBMS都毫无意义。有些人很难理解甚至记住名为Integer1
的字段或可能存有任何东西的序列化值的目的。并且RDBMS无法从序列化实体中提取值,以便对结果进行排序或应用聚合。
难以维护易失性架构。数据库模式应该是常量的原因。其他更高级别取决于它。如果模式在一夜之间发生变化,应用程序也应该更改,以反映新状态。更糟糕的是,视图,存储过程和其他依赖数据库组件变得同样难以维护。
无法强制执行约束,无法创建索引。将序列化字段定义为外键没有意义,或者将其限制为一组特定的值。这取消了大量数据库的自我保护机制。数据完整性越低意味着管理成本越高此外,索引在这里同样没用,使得表格不易于优化。
元数据最终必须存储为数据。想象一下多语言CMS,其中有一个主article
表来存放文章。现在,对于支持的每种语言,都有相应的article_{lang}
表来保存翻译(即article_en
,article_fr
,article_es
等。为了记录文章的现有翻译,应创建“关系”表,其中包含article
表的外键,语言ID,转换表的表名以及应该是的字段。 FK到转换表但不能定义为一个。然后,尝试编写一个查询,计算每篇文章的可用翻译!
尽可能避免非规范化。如果实体可以被分类到一定程度,那么IS-A relations可能就是答案。为了支持任意属性,或者当分类不值得时,a key/value pair table,使用包含规范化数据的表的外键,就足以成为牺牲品。