Database design 什么';在每个数据库引擎中存储二进制标志/布尔值的最佳方式是什么?
我见过一些可能的方法(在一些数据库引擎中,其中一些是同义词):Database design 什么';在每个数据库引擎中存储二进制标志/布尔值的最佳方式是什么?,database-design,flags,bitflags,Database Design,Flags,Bitflags,我见过一些可能的方法(在一些数据库引擎中,其中一些是同义词): TINYINT(1) 布尔 位(1) 枚举(0,1) 字符(0)空 应该注意PHP支持的所有主要数据库引擎,但作为参考,如果还注意到其他引擎,则会更好 我要的是一款最适合阅读的设计。 e、 g.使用WHERE条件中的标志字段进行选择,或按标志分组。 性能比存储空间重要得多(除非大小对性能有影响) 还有更多细节: 在创建表时,我不知道它是否稀疏(如果大多数标志处于打开或关闭状态),但我可以稍后更改表,因此如果我知道有什么可以优化的,应
好吧,在我的例子中,它不值得任何东西,因为在我的应用程序中,每个表都由一个类表示,所有内容都在类中显式定义并有很好的文档记录。我知道这不是你想要的答案,但除了最极端的特殊情况外,在所有情况下差异都是可以忽略的。在每种情况下,仅仅切换数据类型不足以解决性能问题 例如,这里有一些比任何数据类型更改都要好很多的替代方案。当然,每种方法都有其缺点 如果您有200个可选标志,并且一次查询最多1-2行,那么将每个标志都放在自己的表中会获得更好的性能。如果数据真的很稀疏,那就更好了 如果您有200个强制标志,并且只执行单记录抓取,那么应该将它们放在同一个表中 如果您有一小组标志,可以使用位掩码将它们打包到一列中,这在存储方面是有效的,但您将无法(轻松)查询单个标志。当然,当标志可以为空时,这不起作用 或者您可以发挥创意,使用“垃圾维度”概念,即创建一个单独的表,将所有200个布尔标志表示为列。为标志值的每个不同组合创建一行。每行获取一个自动递增主键,您可以在主记录中引用该主键。瞧,主表现在包含1 int,而不是200 int 柱。黑客天堂,DBA噩梦
我想说的一点是,尽管争论哪一个是“最好的”很有趣,但还有其他更重要的问题(比如你引用的评论)。这仅仅是因为当您遇到真正的性能问题时,数据类型既不是问题,也不是解决方案 以上任何一项都可以,我个人倾向于使用
BOOL
,如果它得到适当支持,因为这最能表达您的意图,但我会避免使用ENUM(0,1)
ENUM
的第一个问题是它要求其值为字符串0
和1
看起来像一个数字,因此程序员倾向于发送一个数字
ENUM
的第二个问题是,如果发送错误的值,它将默认为第一个枚举,在某些数据库中,它甚至不会指示错误(我正在查看您的MySQL)。这会使第一个问题变得更糟,因为如果您意外地将其发送到1
而不是“1”
,它将存储值“0”
——这非常违反直觉
<>我不认为这会影响所有的数据库引擎(不知道,没有尝试过它们),但是它影响到足够多,我认为避免它是一个很好的实践。 < p>这个答案是针对ISO/IEC/ANSI标准SQL,并且包括更好的免费软件假装SQL. 第一个问题是您已经确定了两个类别,而不是一个,因此无法对它们进行合理的比较 A.第一类 (1) (4)和(5)包含多个可能值,是一个类别。在WHERE子句中可以轻松有效地使用所有内容。它们具有相同的存储空间,因此存储和读取性能都不是问题。因此,剩下的选择仅基于列的实际数据类型 ENUM是非标准的;更好的或标准的方法是使用查找表;然后这些值在表中可见,而不是隐藏,并且可以由任何报表工具枚举。由于内部处理的原因,ENUM的读取性能将受到小的影响 B.第二类 (2) 和(3)是两个有值元素:真/假;男/女;死/活。这一类与第一类不同。它在您的数据模型和每个平台中的处理方式都是不同的。布尔只是位的同义词,它们是相同的东西。在法律上(SQL方面),所有符合SQL的平台都会处理相同的问题,在WHERE子句中使用它是没有问题的 性能上的差异取决于平台。Sybase和DB2将最多8位打包成一个字节(这里存储并不重要),并动态映射两个字节的能力,因此性能非常好。Oracle在每个版本中做不同的事情,我看到建模人员使用CHAR(1)而不是BIT来克服性能问题。MS在2005年前还不错,但他们在2008年打破了这一局面,因为结果是不可预测的;因此,简单的答案可能是将其实现为CHAR(1) 当然,我们的假设是,您不会做一些愚蠢的事情,例如将8个独立的列打包到一个容器中。不是o