我经常看到VARCHAR(255)被使用,这是有充分的理由吗?(相对于其他长度而言)

228
在多个课程、书籍和工作中,我看到文本字段通常被定义为VARCHAR(255),用于“比较短的”文本。除了一个不错的圆数,有没有其他好的理由选择长度为255?这是过去某个时期的遗留问题吗(无论今天是否适用)?
当然,如果你知道字符串的最大长度,更紧密的限制会更理想。但如果你使用VARCHAR(255),那可能意味着你不知道最大长度,只知道它是一个“比较短的”字符串。
注意:我发现了这个问题(varchar(255) v tinyblob v tinytext),它说VARCHAR(n)需要n+1个字节的存储空间,其中n<=255,对于n>255需要n+2个字节的存储空间。这是唯一的原因吗?这似乎有点武断,因为与VARCHAR(256)相比,您只会节省两个字节,而您可以通过声明VARCHAR(253)来轻松地再节省两个字节。

VARCHAR列长度的255限制已经过时了,现在是64KiB。 - O. Jones
10个回答

221
255被使用是因为它是可以用8位数字计数的最大字符数。它最大化了8位计数的使用,而不会浪费地要求另一个完整的字节来计数超过255的字符。
当以这种方式使用时,VARCHAR只使用字节数+1来存储您的文本,所以您可以将其设置为255,除非您希望在字段中设置一个硬限制(如50)字符的数量。

9
对于使用UTF-8的数据库,这是否仍然成立? - antak
2
@antak:在MySQL中,使用InnoDB引擎时,任何键列的大小不能超过767字节。如果一个VARCHAR列是UTF8编码(意味着每个字符最多可能占用3个字节),那么该列允许的最大长度为floor(767/3) = 255。我猜“767”恰好是出于这个原因而被选择的。 - BlueRaja - Danny Pflughoeft
4
如果字符集是utf8,则varchar(85)是极限,超过这个长度会将长度字节从一个字节变为两个字节。如果是utf8mb4,则为varchar(63)。这些数字非常重要,因为它们是通过使用在线ALTER TABLE扩展VARCHAR的长度的最大值。因此,我通过创建一个带有varchar(2) charset utf8列的表,并查看在ALGORITHM=INPLACE的情况下能够扩展多远来得出这些数字。 - antak
1
考虑到许多“数据库”在早期都存储在磁带上,这种做法就更有意义了。以2的倍数为大小读取数据块是非常常见的。这样,数据可以被最有效地存储(当您在旧的大型计算机上运行时,这些小优化可以决定成败)。 - TMN

130

历史上,在某些数据库管理系统中,255个字符经常是 VARCHAR 的最大长度,如果您要使用UTF-8并索引该列(由于索引长度限制),那么它有时仍然是实际的最大长度。


4
如果你阅读你引用的句子后面的部分,你将找到你要求的确切解释。 - chaos
3
“假的UTF-8”指的是MySQL的“utf8”编码,正如我之前所提到的,它保留(且仅限于)每个字符3个字节。这不是一个很好的UTF-8版本;如果你想在MySQL中使用良好的UTF-8,你必须使用它的“utf8mb4”编码。但人们更可能不知道这一点,并选择“utf8”,而且更可能想要UTF-8而不是其他任何编码,所以他们最终在VARCHAR中获得了最大可索引长度为255个字符。尽管你感到惊讶,但事实就是如此。 - chaos
4
@CharlesBretana: 我已经解释了三次,但没有任何变化。 MySQL的索引长度限制仍然是767字节,编码3字节UTF-8字符所需的字节数仍为3,而floor(767 / 3)仍然是255。你极力寻找混淆的东西的决心真令人费解。 - chaos
1
@CharlesBretana(对于这个派对我来晚了,很抱歉)我不是数据库专家,但我认为chaos所说的是:是的,“伪UTF-8”列可以超过255个字符长,但索引只能在varchar的前255个字符上工作,使其成为完全索引化列的最大值。这只是我理解他解释的部分,我可能错了,我对SQL索引一点都不熟悉。 - Francis Lord
2
如果您仔细查看Chaos的答案,您会注意到它分为两个部分:1. Varchar(255)如此常见的历史原因(在一些旧的DBMS上它曾经是最大值),2.即使今天,由于之前讨论过的索引限制,它仍然是某些人的限制。第1部分和第2部分没有联系。第1部分是问题的实际答案,第2部分是一个副注,因为它解释了即使今天它仍然可能是一个限制的原因,所以它仍然与问题相关。(续 ->) - Francis Lord
显示剩余12条评论

26

可能是因为 SQL Server 和 Sybase(我熟悉的两个数据库)在 VARCHAR 列中字符数的最大限制过去曾经是 255 个。 对于 SQL Server,在1996/1997左右的版本7中发生了变化,但是旧习惯有时难以改变。


22

我将回答字面上的问题:没有好的理由经常使用VARCHAR(255)(的确有原因,正如其他答案所讨论的那样,只是不是好的原因)。即使你在谈论CHAR而不是VARCHAR,你也不会找到很多因为架构师选择了VARCHAR(300)而不是VARCHAR(255)而导致灾难性失败的项目示例。这将是一个几乎毫无意义的问题。


1
255个字节中的1个字节是0.4%。有时您会关心最后半个百分点左右。有时候不在意。如果您的托管和性能成本达到数十美元,那么您可能不在意。如果它们达到了数百万美元,那么它们可能会在意。 - Edward Brey
这更多是关于标准,就像_linting_一样,而不是防止灾难性故障。如果您也认为没有好的理由进行linting,那么这个观点将与之一致。 - Jon

16
当你说2^8时,你得到的是256,但在计算机中数字从0开始。因此,当你得到255时,你可以在IP地址掩码或IP地址本身中进行探测。 255是8位整数的最大值:11111111 = 255 这有帮助吗?

1
使用整数时,您从0开始计数,直到255结束。但是对于字符串中的位置,您从第1个位置开始计数,因此结束在第256个位置似乎是有道理的,因为您从1开始而不是从0开始。我还不完全同意varchar(256),因为它会影响string_length()的结果,但我确实不确定。 - HoldOffHunger
1
@HoldOffHunger 数据库中的字符串可以有零个字符的长度,因此当长度存储在八位时,可允许的长度范围为0到255。如果您想要说所有字符串都必须至少有一个字符,则可以支持具有八位长度的256个字符的字符串。 - phoog

9
注意:我找到了这个问题(varchar(255) v tinyblob v tinytext),其中提到VARCHAR(n)需要n+1字节的存储空间,当n<=255时,需要n+2字节的存储空间,当n>255时。这是唯一的原因吗?这似乎有些武断,因为与VARCHAR(256)相比,您只能节省两个字节,而您可以通过声明VARCHAR(253)来轻松地再节省两个字节。
不是的。声明253并不能节省两个字节。 VARCHAR的实现很可能是一个长度计数器和一个变长的、非终止的数组。这意味着如果你在一个varchar(255)中存储"hello",你将占用6个字节:一个字节用于长度(数字5)和五个字母所需的5个字节。

3
并非所有的数据库都适用这种说法。许多数据库在表中使用给定大小的 varchar 字段,以便在更改行的该字段时无需移动行。 - SingleNegationElimination
是的,你说得对。这取决于具体实现。你需要查看供应商手册以了解情况。 - Stefano Borini
5
可以这样做,但是这种实现方式会背离使用 VARCHAR 而不是 CHAR 的初衷。 - dan04

4

在许多应用程序中,例如Microsoft Office(直到2000或2002版本),每个单元格的最大字符数为255。将数据从支持超过255个字符的程序移动到/从这些应用程序中是一场噩梦。目前,限制越来越少阻碍。


4

一个未签名的1字节数字可以包含[0-255]的范围,包括边缘值。所以当你看到255时,大多数是因为程序员在使用十进制(get the joke?) :)

实际上,在MySQL中,255曾经是你可以给VARCHAR分配的最大大小,并且使用VARCHAR比TEXT具有索引和其他问题方面的优势。


4
0000 0000 -> 这是一个八位二进制数。每个数字代表一个比特位。
计数方式如下: 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. 

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

255可以容纳相当多(不是开玩笑)的值。

随着我们使用更多的位,最大值呈指数级增长。因此,对于许多用途来说,添加更多位数是过度的。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接