Database design 什么';在每个数据库引擎中存储二进制标志/布尔值的最佳方式是什么?

Database design 什么';在每个数据库引擎中存储二进制标志/布尔值的最佳方式是什么?,database-design,flags,bitflags,Database Design,Flags,Bitflags,我见过一些可能的方法(在一些数据库引擎中,其中一些是同义词): TINYINT(1) 布尔 位(1) 枚举(0,1) 字符(0)空 应该注意PHP支持的所有主要数据库引擎,但作为参考,如果还注意到其他引擎,则会更好 我要的是一款最适合阅读的设计。 e、 g.使用WHERE条件中的标志字段进行选择,或按标志分组。 性能比存储空间重要得多(除非大小对性能有影响) 还有更多细节: 在创建表时,我不知道它是否稀疏(如果大多数标志处于打开或关闭状态),但我可以稍后更改表,因此如果我知道有什么可以优化的,应

我见过一些可能的方法(在一些数据库引擎中,其中一些是同义词):

  • TINYINT(1)
  • 布尔
  • 位(1)
  • 枚举(0,1)
  • 字符(0)空
  • 应该注意PHP支持的所有主要数据库引擎,但作为参考,如果还注意到其他引擎,则会更好

    我要的是一款最适合阅读的设计。 e、 g.使用WHERE条件中的标志字段进行选择,或按标志分组。 性能比存储空间重要得多(除非大小对性能有影响)

    还有更多细节:

    在创建表时,我不知道它是否稀疏(如果大多数标志处于打开或关闭状态),但我可以稍后更改表,因此如果我知道有什么可以优化的,应该注意

    此外,如果每行只有一个(或几个)标志与许多(或许多)标志不同,则应注意这一点

    顺便说一句,我在某处读到如下内容:

    使用布尔函数可以做与 使用tinyint,但是它有 语义传达的优势 你的意图是什么,那就是 有价值


    好吧,在我的例子中,它不值得任何东西,因为在我的应用程序中,每个表都由一个类表示,所有内容都在类中显式定义并有很好的文档记录。

    我知道这不是你想要的答案,但除了最极端的特殊情况外,在所有情况下差异都是可以忽略的。在每种情况下,仅仅切换数据类型不足以解决性能问题

    例如,这里有一些比任何数据类型更改都要好很多的替代方案。当然,每种方法都有其缺点

    如果您有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