想象一下带有一组复选框的Web表单(可以选择其中的任何一个或全部)。我选择将它们保存在以逗号分隔的值列表中,该值列表存储在数据库表的一列中。
现在,我知道正确的解决方案是创建第二个表并正确规范化数据库。实施简单的解决方案的速度更快,我想快速地对该应用程序进行概念验证,而不必花太多时间在它上面。
我认为节省时间和更简单的代码在我的情况下是值得的,这是一个合理的设计选择,还是我应该从一开始就对其进行标准化?
在更多情况下,这是一个小型内部应用程序,实际上替代了存储在共享文件夹中的Excel文件。我也在问,因为我正在考虑清理程序并使其更易于维护。我有些不满意,有些是这个问题的主题。
除了由于存储在单个列中的值重复组而违反第一范式之外,逗号分隔的列表还有许多其他更实际的问题:
idlist REGEXP '[[:<:]]2[[:>:]]'
或在MySQL 8.0中:idlist REGEXP '\\b2\\b'
为了解决这些问题,你必须编写大量的应用程序代码,以重新创建RDBMS已经提供的功能,从而更加有效。
逗号分隔的列表是非常错误的,以至于我将其作为本书的第一章:SQL反模式:避免数据库编程的陷阱。
有时候你需要使用非规范化,但是正如@OMG Ponies所提到的,这是例外情况。任何非关系式“优化”都会以一种查询类型为代价,而以其他用途使用数据为代价,因此,请确保你知道哪些查询需要特别处理,以使它们值得进行非规范化处理。
(任何数据类型的)ARRAY都可以解决该异常,只需检查PostgreSQL:postgresql.org/docs/current/static/arrays.html(@Bill:很棒的书,对于任何开发人员或dba来说都是必读的书)
有关PostgreSQL的特定讨论,请参阅dba.stackexchange.com/q/55871/7788。逗号分隔也很糟糕,但是如果仔细应用并考虑后果,在某些情况下,数组字段可能是可接受的性能优化。
@CraigRinger,是的,这是一种非规范化。如果仔细使用,非规范化可能是您要优化的特定查询的正确选择,但必须充分了解它会损害其他查询,这才是正确的。如果这些其他查询对您的应用程序不重要,那么痛苦就少了。
我知道不推荐这样做,但是扮演魔鬼的拥护者:如果有处理唯一性和数据类型的ui(否则会出错或行为不当)的ui会被删除,无论如何ui都会删除并创建它,有一个驱动程序表这些值来自于使其具有唯一性,可以使用“%P%”之类的字段,这些值分别为P,R,S,T,计数无关紧要,排序无关紧要。根据ui的不同,值可以被split []例如在最不常见的情况下从驱动程序表中检查列表中的复选框,而不必转到另一个表来获取它们。
@PrabhuNandanKumar,我会将174行存储在引用您的第一个表的第二个表中。不要存储具有相似数据的174列。