2009-01-28 232 views
68

我不想在这里触发一场宗教战争,但似乎有两种思维方式来表示如何在数据库中表示布尔值。有人说bit是适当的数据类型,而其他人认为tinyint更好。Tinyint vs位

我知道的唯一的区别是这些:

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

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

回答

18

位......除非你是“真/假/找不到文件”氏族

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

而在LINQ2SQL的情况下,真/假,这使得它更容易一点的工作原理编程。两者都有优点。

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

+10

位是空的,所以你仍然可以有T/F/FNF。 – 2009-01-28 18:50:58

+3

邪恶是否等于FNF为NULL? :)真正值得的thedailywtf! – 2009-01-28 18:55:33

+3

NULL等于FNF怎么了? – Pratik 2011-09-09 13:13:52

1

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

1

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

0

我们用int“vector”字段构建所有表。然后我们使用该字段作为32位的集合,我们可以为任何目的分配。 (可能使用一组位来表示一组状态)。如果我们忘记了,避免我们不得不在旗帜领域加入。

+0

这就是所谓的非规范化... – RedFilter 2009-01-28 18:53:48

+1

它也被称为混淆。或者,对于外行人来说,“维修噩梦”。 – 2009-01-28 19:30:27

+6

您可以将所有表格设置为单个TEXT列,并将所有内容放在逗号分隔的位置。那么你永远不需要改变你的数据模型。 – 2009-01-28 19:44:47

0

@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 
13

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

参考文献:

76

当你加一点列到表将在每条记录占据整个字节,而不仅仅是一个单一的位。当你添加第二个比特列时,它将被存储在同一个字节中。第九位列将需要第二个字节的存储空间。具有1位列的表格不会获得任何存储利益。

Tinyint和bit都可以工作,我已经成功地使用,没有强烈的偏好。

-2

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

2

我使用一点,因为它节省了我不得不使用检查约束,并且因为我的ORM会自动将位转换为可为空的布尔值(C#),我非常感谢一次编码。

2

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

1

我不认为我看到了上面提到的问题,但存在无法合计BIT列(例如MIN,MAX,特别是SUM)的问题。我刚刚使用2008年进行了测试,问题仍然存在。这是我最近使用tinyint的最大原因 - 另一个原因是我喜欢tinyint的规模 - 当你的“双值”位标志突然需要更多可能的值时,总是很痛苦。

1

零空间假

无论你的选择,你可以设置为NULL,而不是0,它会占用没有多余的空间(因为数据库几乎总是对的每一个领域的NULL标志每一排,只是坐在那里; more info here)。如果您还确保默认值/最可能的值是false,则可以节省更多空间!

一些空间用于真

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

TINYINT的优点是可以自定义8值bitmask而不用担心管理一堆额外的列,理论上搜索速度更快(单个整数字段与几个位字段)。但是也有一些缺点,例如较慢的排序,奇特的交叉索引以及缺少字段名称。对我而言,这是最大的损失;你的数据库需要外部文档来记录哪些位在哪些位掩码中做了什么。

在任何情况下,避免使用TEXT字段来存储布尔值或它们的集合的诱惑。通过文本搜索对于服务器来说是更多的工作,并且像“开,关,关”这样的任意命名方案可能会影响互操作性。