我看到注释“如果在varchar(20)列中有5000万个介于10到15个字符之间的值,而在varchar( 50 )列中有相同的5000万个值,它们将占用完全相同的空间。这就是varchar相对于char的全部意义所在。”有人能告诉我原因吗?请参阅What is a reasonable length limit on person "Name" fields?
发布于 2012-06-21 15:41:54
MySQL提供了存储引擎的选择。数据的物理存储依赖于存储引擎。
VARCHAR的MyISAM存储
在MyISAM中,VARCHAR通常只占用字符串的实际长度加上一两个字节的长度。这是因为MyISAM的设计局限于表锁定,而不是行锁定功能。性能结果包括更紧凑的缓存配置文件,但也包括更复杂(较慢)的记录偏移量计算。
(实际上,MyISAM根据整个表中出现的列类型,在固定的物理行大小和可变的物理行大小的表格式之间提供a degree of choice。VARCHAR的出现仅更改了默认方法,但是TEXT blob的出现迫使同一表中的VARCHAR也使用可变长度方法。)
物理存储方法对于索引尤其重要,这与表是不同的。MyISAM对CHAR和VARCHAR列都使用空间压缩,这意味着在这两种情况下,较短的数据都占用较少的索引空间。
VARCHAR的InnoDB存储
与当前大多数其他关系数据库一样,InnoDB使用更复杂的机制。最大宽度小于768字节的VARCHAR列将以内联方式存储,并保留与最大宽度匹配的空间。更准确地说,here
对于每个非空的可变长度字段,记录头包含以一个或两个字节为单位的列的长度。仅当列的一部分存储在溢出页的外部或最大长度超过255字节且实际长度超过127字节时,才需要两个字节。对于外部存储的列,双字节长度表示内部存储部分的长度加上指向外部存储部分的20字节指针。内部部分为768字节,因此长度为768+20。20字节的指针存储列的真实长度。
与上面描述的MyISAM相反,InnoDB目前不在其索引中进行空间压缩。
回到问题
然而,以上所有都只是一个实现细节,甚至可能在不同版本之间发生变化。CHAR和VARCHAR之间的真正区别在于语义,VARCHAR(20)和VARCHAR(50)之间的区别也是如此。通过确保无法在VARCHAR(20)中存储30个字符的字符串,数据库使各种处理器和应用程序的工作变得更容易,并且更好地定义了这些处理器和应用程序,这些处理器和应用程序理应集成到可预测的行为解决方案中。这是个大问题。
特别是关于个人名字,this question可能会给你一些实用的指导。全名超过70个UTF-8字符的人无论如何都会有麻烦。
发布于 2012-06-21 14:03:04
是的,这确实是VARCHAR的全部意义所在。它占用的空间和文本的长度一样多。
如果有CHAR( 50 ),那么无论数据有多短,它都将占用50个字节(或字符)(它将被填充,通常由空格填充)。
谁能告诉我原因是什么?
因为人们认为存储大量无用的填充是浪费的,所以他们发明了VARCHAR。
发布于 2012-06-21 15:21:39
The manual声明:
CHAR和VARCHAR类型的声明长度表示要存储的最大字符数。(...)
与CHAR相反,VARCHAR值存储为一个字节或两个字节的长度前缀加上数据。长度前缀表示值中的字节数。如果值需要不超过255个字节,则列使用一个长度字节;如果值可能需要超过255个字节,则使用两个长度字节。
请注意,VARCHAR(255)与VARCHAR(256)不同。
这只是理论。正如habeebperwad所建议的,一行的实际占用空间取决于(引擎)页大小和(硬盘)块大小。
https://stackoverflow.com/questions/11132357
复制相似问题