想象一个带有一组复选框的web表单(可以选择其中的任何一个或所有复选框)。 我选择将它们保存在以逗号分隔的值列表中,这些值存储在数据库表的一列中。
现在,我知道正确的解决方案是创建第二个表并适当地规范化数据库。 实现easy解决方案的速度更快,我希望能够快速获得该应用程序的概念验证,而不必花费太多时间。
我认为节省的时间和更简单的代码在我的情况下是值得的,这是一个可辩护的设计选择,还是我应该从一开始就规范化它?
这是一个小型的内部应用程序,它基本上取代了存储在共享文件夹中的Excel文件。 我这么问也是因为我在考虑清理程序,让它更有可维护性。 其中有一些我不太满意的地方,其中一个就是这个问题的主题。
除了由于一组重复的值存储在单个列中而违反第一范式之外,逗号分隔的列表还有许多其他更实际的问题:
idList REGEXP'[[:<::]]2[[:>:]]'
*为了解决这些问题,您必须编写大量的应用程序代码,重新发明RDBMS已经更有效地提供的功能。
逗号分隔的列表是非常错误的,所以我把它作为我的书《SQL反模式:避免数据库编程的陷阱》的第一章。
有时您需要使用反规范化,但正如@OMG Ponies提到的,这些都是例外情况。 任何非关系“优化”都有益于一种类型的查询,而牺牲了数据的其他用途,因此请确保您知道哪些查询需要特别处理,从而值得对它们进行反规范化。
*MySQL8.0不再支持这种词边界表达式语法。
“原因之一是懒惰”。
这敲响了警钟。 你应该这样做的唯一原因是你知道如何以“正确的方式”去做,但是你已经得出结论,有一个有形的理由不这样做。
话虽如此:如果您选择以这种方式存储的数据是您永远不需要查询的数据,那么可能有理由以您选择的方式存储它。
(有些用户会质疑我上一段的说法,说“你永远不可能知道未来会添加什么需求”。这些用户要么是被误导了,要么是在陈述一种宗教信仰。有时候,按照你面前的需求工作是有利的。)
这样问有很多问题:
逗号分隔列表的另一个问题是确保值一致--存储文本意味着可能出现错别字。。。
这些都是非规格化数据的症状,并且强调了为什么您应该始终为规格化数据建模。 反规范化可以是一种查询优化,在实际需要时应用。