Tinyint vs Bit?


81

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

我知道的唯一区别是:

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

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


1
“以防万一”似乎是一个非常流畅的数据库设计。为什么不将所有内容存储为NVARCHAR(MAX)并覆盖您的所有库?
Stuart Ainsworth '18年

TinyInt是我的偏爱。然后,在对字段进行汇总计数时,无需强制转换。此外,某些前端语言对Bit的解释与其他语言不同,并且使用TinyInt可使验证检查对任何前端语言通用。
格雷戈里·哈特

我只是在phpMyAdmin中遇到了一个奇怪的问题。当我告诉它让该字段为NULL且未设置默认值时,它默认为<em> NULL </ em>而不是NULL。+1 TINYINT顺便说一句
VÖRÖSAmadea

导入时CSV格式文件中TINYINT(1)的情况下,1部作品,但是比特(1)的情况下,你必须把它替换到B'1'
拉雅

Answers:


90

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

可以使Tinyint和bit都起作用,我已经成功使用了两者,并且没有强烈的偏爱。


这是一个非常有帮助的评论,您的声誉很好,但是您有任何引用来支持它吗?是实现细节还是所有引擎都以相同的方式处理它?
Jon z

3
@Jonz有关MySQL,请参见此处
shmosel

19

位...除非您属于“ true / false / file not found”氏族

万一您没有得到参考...

在Linq2SQL的情况下,bit与true / false一起使用可简化编程。两者都有优势。

并且还需要考虑编程维护。如果您(或初级实习生程序员)使用2、3、25、41、167、200等会怎样?在哪里记录?比特是自我记录的,非常通用。


11
这些位为空,因此您仍然可以使用T / F / FNF。
奥斯丁·萨洛宁

3
NULL等于FNF有多邪恶?:)真正值得thedailywtf!
约翰·鲁迪

@Pratik问题是NULL表示数据库中没有值。这并不意味着找不到文件。这样做,您就开始将状态隐式编码到难以记录和混淆的行中。有点像拥有一张物品表。我如何查看商品是否已售出?我可以查看它是否具有销售价格,销售日期,买家名称等。或者我可以通过检查约束来强制执行所有操作,并为所售商品创建一个位字段。
CodeMonkey

15

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

参考文献:




2

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


2

我使用bit是因为它节省了我必须使用检查约束的时间,并且因为我的ORM会自动将bit转换为可为空的布尔值(C#),一旦编码,我将非常感谢。


2

零空间错误

无论您选择什么,都可以设置为,NULL0不会占用任何额外的空间(因为数据库几乎总是NULL每行的每个字段都有一个标志,只坐在那里;更多信息在此处)。如果您还确保默认/最可能的值为false,则可以节省更多空间!

真正的空间

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

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

无论如何,请避免使用TEXT字段存储布尔值或布尔值集的诱惑。对于服务器来说,搜索文本将花费更多的精力,诸如“ on,off,off”之类的任意命名方案可能会损害互操作性。


1

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


1

所有这些理论上的讨论都很棒,但实际上,至少在您同时使用MySQL和SQL Server的情况下,最好为布尔值坚持使用非二进制数据,原因很简单,因为当您使用布尔值时更容易使用正在输出数据,查询等等。如果要实现MySQL和SQLServer之间的互操作性(即在两者之间同步数据),则尤其重要,因为BIT数据类型的处理在两者中是不同的。所以在实践中,如果坚持使用数字数据类型,那么麻烦就少得多。我建议MySQL坚持使用BOOL或BOOLEAN,它们将存储为TINYINT(1)。甚至MySQL Workbench和MySQL Administrator显示BIT数据类型的方式也不是很好(二进制数据有点符号)。


1

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


1
您可以通过将它们强制转换为另一种数据类型来聚合它们-为什么您需要对true / false求和?
马丁·史密斯,

2
我们经常对一个字段进行分组,然后根据结果汇总每个组中有多少个字段是正确的,求和的另一种方法是将整个结果返回到代码中并在其中循环,有时会向客户端返回1000倍的数据。但是强制转换消除了这一点,所以这不是问题。
DavidMårtensson

0

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


2
也称为混淆。或者,对于外行人来说,“维护噩梦”。
罗伯特·巴特

6
您可以将所有表放在单个TEXT列中,然后将所有内容放在逗号分隔的位置。然后,您将无需更改数据模型。
汤姆·H”,2009年

1
我们有一个独特的环境。我们拥有非常庞大的数据集和4 9的正常运行时间,因此更改表是非常禁止的(是涉及复制的两倍)。我们在集中位置跟踪所有位,这有助于避免维护问题。

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

0

TinyInt是我的偏爱。然后,在对字段进行汇总计数时,无需强制转换。此外,某些前端语言对Bit的解释与其他语言不同,并且使用TinyInt可使验证检查对任何前端语言通用。



-2

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


2
您可以(并且应该)轻松地向列添加约束,以仅允许“ T”和“ F”。就是说,报告层应该与数据库完全隔离。您不应仅出于显示列的目的而更改数据库架构。
汤姆H

我同意达里尔的观点。鉴于在常规RDBMS系统中缺乏对布尔类型的支持(此处并非仅MySQL),T / F(实际上我更喜欢Y / N)更具可读性。尽管我在原则上同意汤姆·H(Tom H)的评论,但我认为可读性比他认为的重要得多。在更改其他人的代码时,数据库开发人员不会关注前端!另外,不一定总是清楚开发人员认为1和0是哪种方式。如果我们都以“正确的”老式方式进行操作,那么我们将-1用来表示true和0false。
cartbeforehorse 2012年

在我之前的评论中,我应该补充一点,似乎MySQL不支持CHECK约束,这会使T / F选项变得复杂,因为您无法防止该列被字母的任何其他字符填充。不是很好。
cartbeforehorse 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.