为什么不将每个VARCHAR指定为VARCHAR(65535)?

29

由于Varchar字段的存储要求基于输入字符串的实际长度,指定每个Varchar字段为最大可能值:Varchar(65535)的缺点是什么呢?除了对于最大字段长度超过255个字符需要额外1个字节之外,还有什么缺点吗?

[字符串长度为L的存储需求:如果列值要求0-255字节,则为L + 1字节,如果值可能需要超过255字节,则为L + 2字节]

谢谢!


1
与此相关但不完全相同的问题:https://dev59.com/rXVC5IYBdhLWcg3wihqv - JJJ
感谢大家的评论!我是stackoverflow的新手,非常感激大家的反应。 :-) - tgoneil
5个回答

15

根据文档-表列计数和行大小限制:

每个表(无论存储引擎如何)的最大行大小为65,535字节。存储引擎可能会对此限制施加其他约束,从而降低有效的最大行大小。

最大行大小限制了列的数量(可能还包括大小),因为所有列的总长度不能超过此大小。例如,utf8字符每个字符最多需要3个字节,因此对于一个CHAR(255) CHARACTER SET utf8列,服务器必须分配255×3=765个字节的值。因此,一个表不能包含超过65,535 / 765 = 85个这样的列。

可变长度列的存储包括长度字节,这些字节被计入行大小。例如,VARCHAR(255) CHARACTER SET utf8列需要两个字节来存储值的长度,因此每个值最多可以占用767个字节。

因此,定义一个单一的VARCHAR(65535)列,实际上将您限制在一行中一个单独的列(假设您已经填满了它)。

除此之外,对于某些类型的数据,这样的大尺寸完全不正确 - 如果您有一个可能包含本地和国际号码的电话号码列,您可以选择使用VARCHAR字段来实现此目的,但将其设置为超过20可能是没有意义的(我很慷慨)。

请参见Bill Karwin的这个答案,其中还指出如果临时表生成不必要长的VARCHAR字段(与此类字段的转换为CHAR和再次转换有关-请参见帖子了解详情),也可能会有性能惩罚。


但是我的表确实有额外的列,除了VARCHAR(65535)列(称为“data1”)。 所有这些列都被填充了输入的数据,因为没有任何一个data1列实际上包含接近最大大小的字符串。 - tgoneil
2
@tgoneil - 请尝试将65535个字符插入该列,以及其他列的数据。 - Oded
1
我同意你的警告“(假设你已经填好了)”,并理解它。在我的情况下,可能永远不会有一个实际大小为65535的字符串插入到那个字段中,所以这从一开始就不是问题。看起来限制VARCHAR大小的唯一真正原因是为了在尝试超过预期最大大小时强制出现错误。 - tgoneil
请注意,TEXT和BLOB类型的列不计入MySQL行大小限制(我之前认为VARCHAR也是如此,但我错了)。 - thomasrutter

10
我认为 varchar列长度不仅与存储有关,还涉及数据语义。即在您的系统中将name列指定为varchar(100)表示存储的名称不得超过100个字符。
在存储方面,它们应该是相同的。尽管如此,在没有长度规定时,行大小估算会比有长度规定时更准确,但需要一个统计收集系统来保持varchar大小上的数据分布。

1
可能的一个原因是为了提高与其他应用程序的兼容性。例如,如果您有一个使用100个字符长的“product_no”字段的应用,并且您想要与一个使用类似字段(如长度为40个字符的“model_no”)的应用进行接口操作,那将会很麻烦。 您应用中超过40个字符的“product_no”将被截断,并且您必须找到一种方法在这些应用程序之间进行翻译。

0
例如,MySQL 中的 MEMORY 引擎对 VARCHAR 字段的支持并不理想。该引擎会为每一行保留最大数量的字节,而不是实际使用的长度。因此,如果您定义了一个只有一个 VARCHAR(1000) 列的表,那么无论添加的行是否为空字符串,每一行都将占用 1000*3 个字节的内存。

0
一个原因是字段大小是对输入数据的检查。你真的想让有人输入一个1000个字符的电话号码吗?字段太大是确保垃圾将被输入到您的数据库中的一种方法。您会发现电话号码上写着像这样的话(不是随意选取的例子):
“只跟前台的高个金发女孩说话。”
而不是一个真实的电话号码或者一个包含有关客户注释的电子邮件字段,因为他们没有注释字段?当您尝试发送电子邮件时,这并不起作用。

在数据库中,宽表可能会产生一些问题,因为您可能会遇到意外的记录限制(您可以设计一个比一个记录实际存储的更宽的表,有时这会导致插入操作意外失败),并且数据分散在数据页上会导致性能问题。我知道在SQL Server中使用宽表可能会出现这种情况,如果mysql也遇到类似的问题,我也不会感到惊讶。然而,只有mysql专家才能真正解决这个问题。对于宽字段,索引也可能是一个问题。数据库引擎可能不太倾向于认为索引是有用的。同样,我不确定mysql是否会有这个问题,但这是需要研究的。我知道在SQL Server中,对于所有东西都使用最大字段大小会出现这些问题,mysql可能会有这些问题或者其他SQL Server没有的问题。


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