【问题标题】:Tinyint vs Bit?Tinyint vs 比特?
【发布时间】:2010-10-04 01:55:44
【问题描述】:

我不想在这里引发一场宗教战争,但在如何在数据库中表示布尔值方面似乎有两种思想流派。有人说bit 是合适的数据类型,而其他人则认为tinyint 更好。

我知道的唯一区别是:

  • bit:存储大小为 1 位,可能的值为 0 或 1
  • tinyint:存储大小为 1 字节,可能值为 0-255

当您需要表示布尔值时,哪种数据类型更好? tinyint 是否值得额外开销“以防万一”您需要值 > 1?

【问题讨论】:

  • “以防万一”似乎是一个非常流畅的数据库设计。为什么不将所有内容都存储为 NVARCHAR(MAX) 并覆盖所有基础?
  • TinyInt 是我的偏好。然后,在对字段进行汇总计数时,您不必强制转换它。此外,一些前端语言对 Bit 的解释与其他语言不同,使用 TinyInt 可以使验证检查对任何前端语言都通用。
  • 我刚刚在 phpMyAdmin 中遇到了一个奇怪的问题。当我告诉它让该字段为 NULL 并且没有设置默认值时,它默认为 NULL 而不是 NULL。 +1 为 tinyint 顺便说一句
  • 当导入表单 csv 文件 1 在 tinyint(1) 的情况下有效,但在 bit(1) 的情况下,您必须将其替换为 b'1'
  • 在 SQL server 中位数据类型是 1 字节,tinyint 也是 1 字节。您可以使用内置函数 DATALENGTH(@MyVariable) 进行交叉检查

标签: sql mysql sql-server types


【解决方案1】:

TinyInt 是我的偏好。然后,在对字段进行汇总计数时,您不必强制转换它。此外,一些前端语言对 Bit 的解释与其他语言不同,使用 TinyInt 可以使验证检查对任何前端语言都通用。

【讨论】:

    【解决方案2】:

    错误的零空间

    无论您选择什么,您都可以设置为NULL 而不是0,它不会占用额外的空间(因为数据库几乎总是为每个字段都有一个NULL 标志每一排,就坐在那里;more info here)。如果您还确保默认/最可能的值为false,您将节省更多空间!

    一些空间是真实的

    表示true的值需要字段类型定义的空间;使用 BIT 只会在一个表有多个这样的列时节省空间,因为它每 8 个字段使用一个字节(而 TINYINT 每个字段使用一个字节)。

    TINYINT 的优点是允许您自定义一个 8 值 bitmask 而无需担心管理一堆额外的列,并且搜索理论上更快(单个整数字段与多个位字段)。但也有一些缺点,例如排序较慢、花哨的交叉索引内容以及缺少字段名称。对我来说,这是最大的损失;您的数据库将需要外部文档来记录哪些位在哪些位掩码中做了什么。

    无论如何,请避免使用TEXT 字段来存储布尔值或它们的集合。对于服务器来说,搜索文本需要做更多的工作,而像“开、关、关”这样的任意命名方案可能会损害互操作性。

    【讨论】:

      【解决方案3】:

      我认为我没有看到上面提到的,但存在无法聚合 BIT 列(例如 MIN、MAX,尤其是 SUM)的问题。我刚刚使用2008进行了测试,问题仍然存在。这是我最近使用 tinyint 的最大原因——另一个是我喜欢 tinyint 的扩展方式——当你的“双值”位标志突然需要更多可能的值时,这总是很痛苦。

      【讨论】:

      • 您可以通过将它们转换为另一种数据类型来聚合它们 - 为什么需要对真/假求和?
      • 我们经常对一个字段进行分组,并按结果总结每个组中有多少另一个字段为真,求和的替代方法是将整个结果返回给代码并在那里循环,有时会导致向客户端返回 1000 倍的数据。但铸造消除了这一点,所以这不是问题。
      【解决方案4】:

      所有这些理论上的讨论都很棒,但实际上,至少如果您使用 MySQL 并且真的也用于 SQLServer,那么最好为您的布尔值坚持使用非二进制数据,原因很简单,因为它更容易工作当你输出数据,查询等等。如果您试图实现 MySQL 和 SQLServer 之间的互操作性(即您在两者之间同步数据),这一点尤其重要,因为两者对 BIT 数据类型的处理是不同的。所以在实践中,如果你坚持使用数字数据类型,你会少很多麻烦。我建议 MySQL 坚持使用存储为 TINYINT(1) 的 BOOL 或 BOOLEAN。即使 MySQL Workbench 和 MySQL Administrator 显示 BIT 数据类型的方式也不好(它是二进制数据的一个小符号)。所以要务实,省去麻烦(不幸的是,我是根据经验说话)。

      【讨论】:

        【解决方案5】:

        我在适当的时候使用位。除了它在语义上是正确的类型(语义计数!)之外,单行中的多个位字段(最多 8 个)(无论如何在 SQL Server 上)可以合并到一个存储字节中。在第 8 个之后,接下来的 8 个需要一个额外的字节,以此类推。

        参考资料:

        【讨论】:

          【解决方案6】:

          Bit...除非你属于“真/假/找不到文件”氏族

          In case you didn't get the reference...

          在 Linq2SQL 的情况下,bit 与 true/false 一起工作,这使得编程更容易。两者各有优势。

          还需要考虑编程维护。如果您(或初级实习程序员)使用 2、3、25、41、167、200 等会发生什么?这是在哪里记录的? Bits 是自我记录的,非常普遍。

          【讨论】:

          • 位可以为空,因此您仍然可以拥有 T/F/FNF。
          • NULL 等于 FNF 有多邪恶? :) 真不愧是dailywtf!
          • @Pratik 问题是 NULL 表示数据库中没有值。这并不意味着找不到文件。这样做,您开始将状态隐式编码到难以记录和混淆的行中。有点像有一个项目表。如何查看商品是否已售出?我可以查看它是否有销售价格、销售日期、买家姓名等。或者我可以通过检查约束来强制执行所有这些,并为已售商品创建一个位字段。
          【解决方案7】:

          我使用 bit 是因为它让我不必使用检查约束,而且我的 ORM 会自动将 bit 转换为可为空的布尔值 (C#),我非常感谢编码后的这一点。

          【讨论】:

            【解决方案8】:

            我喜欢将 char(1) 与 'T' 或 'F' 一起使用。是的,它可以与其他值一起被滥用,但至少它很容易在报告或其他难以使用位或二进制值的地方查看。

            【讨论】:

            • 您可以(并且应该)轻松地向列添加一个约束,只允许“T”和“F”。话虽如此,报告层应该与数据库完全分离。您不应该仅仅为了列的显示方式而更改数据库架构。
            • 我同意达里尔的观点。鉴于在一般 RDBMS 系统中缺乏对布尔类型的支持(MySQL 并不孤单)T/F(实际上我更喜欢 Y/N)更具可读性。虽然我原则上同意 Tom H 的 cmets,但我认为可读性比他认为的要重要得多。数据库开发人员在更改别人的代码时不要看前端!此外,开发人员认为 1 和 0 是哪一种方式并不总是很清楚。如果我们都以“正确”的老式方式进行操作,我们将使用-1 表示真,0 表示假。
            • 对于我之前的评论,我应该补充一点,似乎 MySQL 不支持 CHECK 约束,这会使 T/F 选项复杂化,因为您无法阻止该列被填充字母表中的任何其他字符。不好。
            【解决方案9】:

            当您向表中添加一个位列时,它将在每条记录中占据一个完整的字节,而不仅仅是一个位。当您添加第二个位列时,它将存储在同一个字节中。第九位列将需要第二个字节的存储空间。具有 1 位列的表不会获得任何存储优势。

            tinyint和bit都可以用,我都用过成功,没有强烈的偏好。

            【讨论】:

            • 这是一个非常有用的评论,您的声誉也很好,但是您有任何参考资料来支持它吗?它是一个实现细节还是所有引擎都以相同的方式处理它?
            • @Jonz 对于 MySQL,请参见 here
            • 从@shmosel 的参考中很清楚 1 bit(1) 列占用 1 字节,但不清楚二、三、四……直到八位 (1)列采用相同的字节。我在网上搜索过,没有成功。你也可以参考一下吗?我很想知道,如果我说我的表需要四个布尔列,是否值得使用 bit(1) 列而不是 tinyint(1)s 来节省存储空间。谢谢。
            • @assensi 好点。您始终可以使用单个 BIT(n) 代替 n 字段。或者您可以使用常规的INT 并将每个布尔值存储为位。但是,如果您要使用单独的字段,我认为 TINYINT 在 MySQL 中是 usually preferredBIT
            【解决方案10】:

            如果您使用的是 MySQL,那么不建议使用 BIT 数据类型 - http://www.xaprb.com/blog/2006/04/11/bit-values-in-mysql/

            【讨论】:

              【解决方案11】:

              【讨论】:

              • 嗯,看起来更像是“为什么不应该使用 MySQL”条目... :-)
              • 已修复:在 5.0.23、5.1.12 变更日志中注明。表中的 BIT 列可能会导致使用该表的连接失败。
              【解决方案12】:

              根据定义,布尔值只允许两个值。为什么你需要更多的东西呢?如果您需要三(或更多)状态逻辑,则使用更大的数据类型,但我会(并且确实)坚持使用标准布尔逻辑的位字段。

              【讨论】:

                【解决方案13】:

                以前的 StackOverflow 帖子:What is the difference between BIT and TINYINT in MySQL?

                在添加新的“BOOL”列时,MySQL 实际上使用 TINYINT。

                我会坚持使用 BOOL(又名 TINYINT)并继续生活。

                【讨论】:

                  【解决方案14】:

                  @Kevin:我相信你可以在位域上使用group by(SQL Server 2005):

                  declare @t table (
                      descr varchar(10),
                      myBit1 bit, 
                      myBit2 bit
                  )
                  insert into @t values ('test1', 0, 1)
                  insert into @t values ('test2', 1, 0)
                  insert into @t values ('test3', 1, 1)
                  insert into @t values ('test4', 0, 0)
                  
                  select myBit1, count(myBit1) from @t group by myBit1
                  select myBit2, count(myBit1) from @t group by myBit2
                  

                  结果:

                  myBit1 
                  ------ -----------
                  0      2
                  1      2
                  
                  myBit2 
                  ------ -----------
                  0      2
                  1      2
                  

                  【讨论】:

                    【解决方案15】:

                    我们使用 int "vector" 字段构建所有表。然后,我们将该字段用作我们可以为任何目的分配的 32 位的集合。 (可能对一组状态使用一组位)。如果我们忘记了,避免我们不得不继续添加标志字段。

                    【讨论】:

                    • 也叫混淆。或者,对于外行来说,“维护噩梦”。
                    • 您可以将所有表格设置为单个 TEXT 列,并将所有内容以逗号分隔。那么您将永远不必更改数据模型。
                    • 我们的环境有些独特。我们有非常大的数据集和 4 个 9 的正常运行时间,因此更改表是相当禁止的(涉及复制的两倍)。我们在一个集中位置跟踪所有位,这有助于避免维护问题。
                    【解决方案16】:

                    我刚刚尝试按位分组(SQL Server 2k5),它对我来说效果很好。我喜欢为应用程序使用正确的数据类型。如果它是一个真/假字段,那么我使用的是位......

                    【讨论】:

                      猜你喜欢
                      • 2012-10-18
                      • 2015-11-24
                      • 2011-05-16
                      • 2014-01-24
                      • 2014-12-19
                      • 1970-01-01
                      • 2011-04-14
                      • 2023-03-06
                      • 1970-01-01
                      相关资源
                      最近更新 更多