是否有充分的理由使我看到VARCHAR(255)经常使用(相对于另一种长度)?


158

在多门课程,书籍和工作中,我已经看到定义为VARCHAR(255)的文本字段是“短”文本的默认字段。有什么好的理由经常选择255的长度,而不是一个不错的整数有?是有一定理由(过去是否适用)从过去某个时间开始的坚持吗?

我当然知道,如果您以某种方式知道字符串的最大长度,则更严格的限制将更为理想。但是,如果您使用的是VARCHAR(255),则可能表明您不知道最大长度,只是它是一个“短”字符串。


注意:我发现这个问题(VARCHAR(255)V TINYBLOB v TINYTEXT),它表示,VARCHAR(Ñ)需要Ñ为1个字节的存储Ñ <= 255,Ñ为2个字节的存储Ñ > 255。这是唯一原因吗?这似乎是任意的,因为与VARCHAR(256)相比,您只节省了两个字节,并且可以通过声明VARCHAR(253)来轻松保存另外两个字节。

Answers:


109

从历史上看,VARCHAR在某些DBMS中,255个字符通常是a的最大长度,如果您想使用UTF-8并对列进行索引(由于索引长度的限制),有时有时仍然会成为有效的最大长度。


4
@CharlesBretana:如果您阅读了引用的其余句子,则会找到您所要求的确切说明。
混乱

2
@CharlesBretana:“假UTF-8”是指MySQL的“ utf8”编码,正如我提到的那样,每个字符保留(并限于)3个字节。这不是UTF-8的很好的版本;如果要在MySQL中使用合适的UTF-8,则必须使用其“ utf8mb4”编码。但是人们比其他任何编码都更可能不知道并使用“ utf8”,并且更可能想要UTF-8,因此,在VARCHAR中,他们最终使用的最大可索引长度为255个字符。尽管您感到惊讶。
混乱

3
@CharlesBretana:我现在已经解释了三遍,没有一件事情发生改变。MySQL的索引长度限制仍然是767个字节,对3个字节的UTF-8字符进行编码所需的字节数仍然是3,而floor(767/3)仍然是255。 。
混乱

1
@CharlesBretana(很抱歉,这次聚会迟到了)我不是数据库专家,但我认为混乱是在说:是的,“假UTF-8”列的长度可以超过255个字符,但是索引会仅适用于varchar的前255个字符,如果您希望对其进行完全索引,则实际上使其成为一列的最大值。现在,这只是我对他的解释的理解,我可能是错的,我根本不是SQL索引方面的专家。
弗朗西斯·洛德

2
@CharlesBretana如果正确看一下Chaos的答案,您会注意到它分为两部分:1. Varchar(255)背后的历史原因是如此普遍(它曾经是某些旧DBMS的最大值),2。即使在今天,由于前面讨论的索引限制,它仍然是某些限制,第1部分和第2部分未链接。第1部分是对该问题的实际答案,第2部分是与该问题仍然相关的旁注,因为它解释了为什么即使在今天,它仍然可能是一个限制。(续->)
弗朗西斯·罗德

161

使用255是因为它是最多可以用8位数字计数的字符数。它最大程度地利用了8位计数,而毫不费力地需要另一个完整字节来计数255个以上的字符。

当以这种方式使用时,VarChar仅使用字节数+ 1来存储文本,因此您最好将其设置为255,除非您要对该字段中的字符数进行硬限制(例如50)。


90
我喜欢那句话:“很需要另一个完整的字节”。=)
MusiGenesis'Aug

7
这对于varchars为UTF-8的DB是否成立?
antak

1
@antak:在MySQL中,使用InnoDB,任何键列都不能大于767个字节。如果VARCHAR列为UTF8(意味着每个字符最多可能占用3个字节),则该列的最大允许长度为floor(767/3)=255。我假设正是出于这个原因选择了“ 767”。
BlueRaja-Danny Pflughoeft

1
如果字符集为utf8varchar(85)则交叉限制了长度字节从一到两个字节的限制。如果是utf8mb4,那就是varchar(63)。这些很重要,因为它们是通过使用联机ALTER TABLE可以将VARCHAR的长度扩展到的最大值。因此,我通过创建带有varchar(2) charset utf8列的表并查看给定的范围可以扩展多远而得出这些数字ALGORITHM=INPLACE
antak

当您考虑将许多Back Back The Day的“数据库”存储在磁带上时,这显得更加有意义。读取以“ 2”的倍数大小的“块”中的数据非常普遍。这样,数据的存储效率最高(当您在旧的大型机上运行时,像这样的小效率就是“成即停”的优化)。
TMN

23

可能是因为SQL Server和Sybase(我所熟悉的两个)过去一VARCHAR列的字符数最多为255个字符。对于SQL Server,这在1996/1997左右的版本7中发生了变化...但是旧习惯有时会死掉。


8
+1用于引用特定的数据库和版本。而“旧习惯难改”可能是所有问题中最真实的答案。
安德鲁M

17

我要回答字面上的问题: ,您没有看到这么频繁使用VARCHAR(255)的充分理由(确实有原因,正如其他答案所讨论的那样,只是不好的原因)。由于架构师选择了VARCHAR(300)而不是VARCHAR(255),因此您不会找到许多因灾难性失败而失败的项目示例。即使您是在谈论CHAR而不是VARCHAR,这也几乎是一个无关紧要的问题。


255个字节中的1个字节为0.4%。有时您会关心最后一个百分点左右。有时候你没有。如果托管和性能成本高达数十美元,那么您可能不在乎。如果他们成千上万,他们可能会做到。
爱德华·布雷

2
@EdwardBrey:如果摩尔定律仍然成立,那么我的答案比我写它时的答案高16倍。
MusiGenesis

除非我们发现16倍多的计算机可以帮助我们的方法。速度仍然是一项功能。
爱德华·布雷

14

当您说2^8得到时256,但计算机术语中的数字从数字开始0。这样,您就255可以在IP的Internet掩码或IP本身中对其进行探测。

255 是8位整数的最大值: 11111111 = 255

有帮助吗?


1
对于整数,您从0开始计数,然后从255结束。但是对于字符串中的位置,您从第1位开始计数,所以从第256位结束没有意义,因为您从1开始而不是0?由于string_length()的结果,我还不太完全同意varchar(256),但我确实不确定。
HoldOffHunger

1
数据库中的@HoldOffHunger字符串的长度可以为零个字符,因此,当长度以8位存储时,允许的长度范围在0到255之间。如果您想说所有字符串都必须至少包含一个字符,那么您可以可以支持八位长度的256个字符的字符串。
phoog

7

注意:我发现这个问题(VARCHAR(255)V TINYBLOB v TINYTEXT),它表示,VARCHAR(Ñ)需要Ñ为1个字节的存储Ñ <= 255,Ñ为2个字节的存储Ñ > 255。这是唯一原因吗?这似乎是任意的,因为与VARCHAR(256)相比,您只节省了两个字节,并且可以通过声明VARCHAR(253)来轻松保存另外两个字节。

不。您不必通过声明253来保存两个字节。varchar的实现很可能是一个长度计数器和一个可变长度的非终止数组。这意味着,如果将“ hello”存储在varchar(255)中,则将占用6个字节:一个字节表示长度(数字5),而5个字节表示五个字母。


3
该语句并非对所有数据库都适用。许多数据库在表中使用给定大小的varchar字段,因此当该字段更改为一行时,它们不必四处移动行。
SingleNegationElimination

是的,你是对的。它取决于实现。您必须查看供应商手册以了解情况如何
Stefano Borini 2009年

2
它可能是允许的,但是以VARCHAR这种方式实现会破坏使用代替代替的全部意义VARCHARCHAR
10年

4

一个无符号的1字节数字可以包含范围[0-255](含)。因此,当您看到255时,主要是因为程序员认为10(开个玩笑?):)

实际上,有一阵子,255是您可以在MySQL中提供VARCHAR的最大大小,并且在索引和其他问题上使用VARCHAR优于TEXT有优势。


4

在许多应用程序中,例如MsOffice(直到2000或2002版),每个单元格的最大字符数为255。将数据从能够处理每个字段超过255个字符的程序移入/移出这些应用程序是一场噩梦。目前,限制越来越少。


2

0000 0000 >这是一个8位二进制数。一个数字代表一位。

您数如下:

0000 0000 →(0)

0000 0001 →(1)

0000 0010 →(2)

0000 0011 →(3)

每个位可以是两个值之一:开或关。最高总数可以用乘法表示:

2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 - 1 = 255

要么

2^8 - 1. 

我们减去一个是因为第一个数字是0。

255可以容纳很多(没有双关语)值。

当我们使用更多位时,最大值将呈指数增长。因此,出于许多目的,增加更多的位是过大的。


1

另一个原因可能是,在Windows上非常老的数据访问库(例如RDO和ADO,COM版本不是ADO.NET)中,您必须调用特殊方法GetChunk才能从具有超过255个字符的列中获取数据。如果将varchar列限制为255,则不需要这些额外的代码。

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.