首先看下为什么MySQL中varchar会经常设置成varchar(255)?

MySQL 数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255(根据不同版本数据库来定)。在 MySQL5.0以上的版本中,varchar数据类型的长度支持到了65535,也就是说可以存放65532个字节的数据,起始位和结束位占去了3个字 节,也就是说,在4.1或以下版本中需要使用固定的TEXT或BLOB格式存放的数据可以使用可变长的varchar来存放,这样就能有效的减少数据库文件的大小。

varchar(255) 并不是最优的字符长度,最优还是应该根据实际需要设置。但是255能够兼容低版本,只需要一个字节就能表示其长度,是保证能少出错的一个很好的默认值.

单列索引限制

InnoDB存储引擎的表索引的前缀长度最长是767字节(bytes),起因是2^8×3-1。767表示3个字符最大占用空间(utf8)。

所以,如果需要建索引,就不能超过 767 bytes;utf8编码时 255*3=765bytes ,恰恰是能建索引情况下的最大值。

但是在5.5以后,开始支持4个字节的utf8(utf8mb4)。255×4>767, 于是增加了一个参数叫做innodb_large_prefix。这个参数默认值是OFF(5.7默认为ON)。当改为ON时,允许列索引最大达到3072。

联合索引限制

3072

InnoDB一个page的默认大小是16k。由于是Btree组织,要求叶子节点上一个page至少要包含两条记录(否则就退化链表了)。

所以一个记录最多不能超过8k。又由于InnoDB的聚簇索引结构,一个二级索引要包含主键索引,因此每个单个索引不能超过4k (极端情况,pk和某个二级索引都达到这个限制)。由于需要预留和辅助空间,扣掉后不能超过3500,向下取个“整数”就是(1024*3)。

varchar(20)与varchar(255)

1.MySQL建立索引时,如果没有限制索引的大小,索引长度会默认采用的该字段的长度.

varchar(20)和varchar(255)对应的索引长度分别为203(utf-8)(+2+1),2553(utf-8)(+2+1),其中”+2”用来存储长度信息,“+1”用来标记是否为空,加载索引信息时用varchar(255)类型会占用更多的内存; (当字段定义为非空的时候,是否为空的标记将不占用字节)

2.varchar(20)与varchar(255)都是可变的字符串

通常情况下使用varchar(20)和varchar(255)保存较短的字符串’hello world’时,占用的空间都是一样的,但使用长度较短的列却有巨大的优势。较大的列使用更多的内存,MySQL通常会分配固定大小的内存块来保存值,这对排序或使用基于内存的临时表尤其不好。同样,也会发生在使用文件排序或者基于磁盘的临时表时。

(当使用ROW_FORMAT=FIXED创建MyISAM表时,会为每行使用固定的长度空间,这样设置不同的varchar长度值时,存储相同数据所占用的空间是不一样)

3.字符串较长

当20<字符长度<255,varchar(20)会报错,varchar(255)会正常插入.

4.字符串特别长

字符长度>255,可以选择更大的值,VARCHAR(M)定义的列长度为可变长字符串,M取值可以为0~65535(64K)之间,(VARCHAR的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是65,532字节)

但是,服务器选项 innodb_large_prefix关闭时,InnoDB 引擎单一字段索引的长度最大为 767 字节,当字节超过这个长度时,必须建立小于等于767字节的前缀索引。

此外,BLOB和TEXT类型的列只能创建前缀索引。

前缀索引能提高索引建立速度和检索速度,但是下面情况是无法使用前缀索引的:

  • 索引覆盖扫描

  • 通过索引的排序(order by, group by)

varchar类型限制

1.存储限制

varchar 字段是将实际内容单独存储在聚簇索引之外,内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过65535字节。

2.编码长度限制

字符类型若为gbk,每个字符最多占2个字节,最大长度不能超过32766字符;

字符类型若为utf8,每个字符最多占3个字节,最大长度不能超过21845字符。

若定义的时候超过上述限制,则varchar字段会被强行转为text类型,并产生warning。

3. 行长度限制

实际应用中,导致varchar长度限制的通常是一行定义的长度,就是表里所有字段定义的长度总和。https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html

MySQL要求一行的定义长度不能超过65535。若定义的表长度超过这个值,则提示

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。

之所以可以用TEXT或者BLOBS代替,官方解释如下:

The internal representation of a MySQL table has a maximum row size limit of 65,535 bytes, even if the storage engine is capable of supporting larger rows. BLOB andTEXT columns only contribute 9 to 12 bytes toward the row size limit because their contents are stored separately from the rest of the row.

TEXT和BLOB在行限制中,只占用其中的9-12字节,因为实际内容的存储是和其他行分离的.

varchar在一般情况下存储都够用了。如果遇到了大文本,考虑使用TEXT/MEDIUMTEXT/LONGTEXT,LONGTEXT最大能到4G。

留言

2018-08-11