我们有一个数据库表,我称之为 TIMES。它传统上看起来像这样:
ID Blah1 Blah2 Blah3 Description
1 a b c Day
2 d e f Night
(我添加 Blah 列主要是为了表明表中存在更多列,但与我们尝试进行的升级没有直接关系。)
我们想为从数据库中获得的结果添加一些语言支持。所以我的建议是:
a) 偷懒,只为语言添加一个新列,给我们
ID Blah1 Blah2 Blah3 Description Language
1 a b c Day English
2 d e f Night English
1 a b c Tag German
2 d e f Nacht German
或者,最好是 b) 进行一些规范化并创建一个仅包含相关值的新表:
ID Description Language
1 Day English
2 Night English
1 Tag German
2 Nacht German
我们的数据库人员说,好吧,我们可以只使用原始表并将所有内容都包含在 xml 中...这样我们就可以节省行数。
ID Blah1 Blah2 Blah3 Language
1 a b c <TimeDescriptions>
<TimeDescription language='English'>
Day
</TimeDesciption>
<TimeDescription language='German'>
Tag
</TimeDesciption>
</TimeDescriptions>
2 d e f <TimeDescriptions>
<TimeDescription language='English'>
Night
</TimeDesciption>
<TimeDescription language='German'>
Nacht
</TimeDesciption>
</TimeDescriptions>
“节省行数”?我不是真正的数据库专家,但这对我来说听起来很奇怪。当然,它会节省一些行……但当行本身更长时,这是总体上的胜利吗? (很有可能)除此之外,它似乎打破了我习惯的规范化规则。我也知道可以在 SQL 中使用 XML 并对其进行搜索(尽管我还没有这样做,并且对细节非常模糊),但我只是看不到这样做的好处。
当我问起这件事时,他开始生气,所以我退缩了,但我仍然想知道我是否遗漏了什么。显然缺少很多细节,但我不是在寻找详细的分析......我只是想知道这是否合理。
编辑:啊。您可能会认为我在这里已经足够长的时间学会了正确格式化,但我不知何故弄乱了最后一点……我会尝试修复它,但欢迎进行其他编辑。
请您参考如下方法:
Sure, it will save some rows...but is that a win overall, when the rows themselves are much longer?
可能吧。但这意味着页面中可以容纳更少的行,这通常意味着更多的磁盘访问和更多的磁盘 I/O。这些行现在看起来还不错,但是如果您支持十几种语言,那么单是 XML 数据,每行就可能需要 1Kb。我粗略计算的经验法则是每页使用 8Kb(有时可以调整,具体取决于您的 dbms),因此每页只有 8 行。
另外,这意味着使用类似 WHERE Description = 'Day' 的子句查询行要困难得多。 (不过,这在您的应用程序中可能无关紧要。)此外,使用现有结构,如果需要,您可以根据“语言”对表进行分区。
向原始表中添加新列似乎 引入了多值依赖关系,这将违反 4NF。 (语言->>描述)但是如果您可以将其建模为复合属性,则可以消除这种依赖性。
复合属性:复合属性是具有内部结构的属性,dbms a) 完全忽略或 b) 提供函数和运算符以便用户可以操作这些部分。最常见的例子是“日期”类型的列。日期有内部结构——年、月、日。它们具有内部多值依赖关系。但是 dbms 提供了函数和运算符,可以在您需要时获取这些部分。
您的 dbms 可能会使用复合、复合、用户定义、类型、 列和属性来描述此功能。
如果您的 dbms 支持用户定义的类型,您可以为特定于语言环境的词创建一个类型,并在表中使用它。
但无论如何,这不应该是见仁见智的事情。您应该能够在一个下午或一天内测试具有代理键的 5NF 方法、没有代理键的 5NF、具有复合或用户定义类型的 5NF 以及 XML。然后再花一个下午的时间确保索引和查询工作顺利进行,这样性能差异就不仅仅是由于错误、匆忙或无知造成的。
最后,权衡最佳性能与维护成本。 (并用这些新获得的技能更新您的简历。)




