MYSQL 的VARCHAR 类型字段的最多能存储多少字符?模糊记得 VARCHAR 最多能存65535个字符,真的吗?

理论上,一个字符类型能存的字符数量跟选取的编码字符集和存储长度限制肯定是有关系的,字符编码长度越小,长度上限越大,能存的字符就越多。

OK!我们先用字符编码长度最小的latin1做测试:

[testdb]> create table t5(name varchar(65535)) charset=latin1;

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

[testdb]> create table t5(name varchar(65534)) charset=latin1;

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

[testdb]> create table t5(name varchar(65533)) charset=latin1;

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

[testdb]> create table t5(name varchar(65532)) charset=latin1;

Query OK, 0 rows affected (0.01 sec)

一番折腾下来,我们发现被 Row size 限制了,不过测试结果很明显,使用 latin1字符编码时varchar最多能存 65532ge字符,真的如此吗?

答案是 NO!

这个结论明显经不起推敲,参考文档,VARCHAR存储长度超过255的字符串时,需要使用2个字节的前缀表示存储字符串占用的存储空间长度(字节数)。

(2个字节16bit,2^16-1=65535 这也从从另一个层面解释了65535 字节这个限制)

参考MYSQL 5.7 官档:

Values in VARCHAR columns are variable-length strings. The length can be specified as a value from 0 to 65,535.

The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used.

See Section C.10.4, “Limits on Table Column Count and Row Size”.

In contrast to CHAR, VARCHAR values are stored as a 1-byte or 2-byte length prefix plus data.

The length prefix indicates the number of bytes in the value.

A column uses one length byte if values require no more than 255 bytes, two length bytes if values may require more than 255 bytes.

那么,65535-2 =65533 ,但是 create table t5(name varchar(65533)) charset=latin1 依然执行失败了,why?

因为我们忽略了行格式中的 null 标志位,因为我们的表只定义了一个字段,所以标志位需要占用行的一个字节(关于null标志位这里不延伸)。

将name字段定义字段为not null 即可以关闭null 标志位,继续测试:

root@localhost 17:00: [testdb]> create table t6(name varchar(65534) not null) charset=latin1;

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

root@localhost 17:00: [testdb]> create table t6(name varchar(65533) not null) charset=latin1;

Query OK, 0 rows affected (0.01 sec)

OK!测试符合理论!

那么在 utf8mb4 下最多能存多少个字符呢?

首先我们来看下试验环境的字符集和行格式相关设置,MYSQL 版本是5.7.22。数据库默认字符集是 utf8mb4

[testdb]> show variables like '%char%';

+--------------------------+----------------------------------------------------------------+

| Variable_name | Value |

+--------------------------+----------------------------------------------------------------+

| character_set_client | utf8 |

| character_set_connection | utf8 |

| character_set_database | utf8mb4 |

| character_set_filesystem | binary |

| character_set_results | utf8 |

| character_set_server | utf8mb4 |

| character_set_system | utf8 |

| character_sets_dir | /opt/mysql/mysql-5.7.22-linux-glibc2.12-x86_64/share/charsets/ |

+--------------------------+----------------------------------------------------------------+

8 rows in set (0.00 sec)

创建一个表,指定字段长度为65535:

[testdb]> create table t3(name varchar(65535) primary key);

ERROR 1074 (42000): Column length too big for column 'name' (max = 16383); use BLOB or TEXT instead

根据以上错误信息提示,字段长度最大值为16383;为什么是16383这个值,而不是其他值?

首先依然是被 65,535这个行长度限制了,我们来看看官档中关于 Row size 的描述。

Row Size Limits

The maximum row size for a given table is determined by several factors:

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 and TEXT columns only contribute 9 to 12 bytes toward the row size limit because their contents are stored separately from the rest of the row.

也就是说,即使你的存储引擎支持更大的行长度,但是MYSQL 依然限制 Row size为65535;

BLOB and TEXT 这两种类型字段只占用行存储的9-12个字节,其他的内容分开存储。

其次创建表时没有指定表的字符集,所以默认继承数据库字符集 utf8mb4;

在utf8mb4 编码中,字符的最大编码长度是4,比如中文;

所以为了保证存储的字符串实际存储空间小于65535字节,字符串长度不能大于 floor(65535/4)=16383

但是以16383长度再次创建表格,依然提示错误,why?

[testdb]> create table t3(name varchar(16383) primary key);

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

注意看提示信息!这次不再是提示 Column length too big ,而是 Specified key was too long;

Look 下面的官方描述:

Both DYNAMIC and COMPRESSED row formats support index key prefixes up to 3072 bytes.

This feature is controlled by the innodb_large_prefix configuration option, which is enabled by default.

See the innodb_large_prefix option description for more information.

原来 DYNAMIC and COMPRESSED 行格式默认支持索引长度不能超过3072字节.

而我们的 name是聚集索引,整个字段值作为索引键值,所以索引长度必然超限。

而且它还告诉我们,可通过 innodb_large_prefix这个变量来控制这个特性。

检查下我们的试验环境,行格式刚好是 dynamic :

[testdb]> show variables like '%format%';

+---------------------------+-------------------+

| Variable_name | Value |

+---------------------------+-------------------+

| binlog_format | ROW |

| date_format | %Y-%m-%d |

| datetime_format | %Y-%m-%d %H:%i:%s |

| default_week_format | 0 |

| innodb_default_row_format | dynamic |

| innodb_file_format | Barracuda |

| innodb_file_format_check | ON |

| innodb_file_format_max | Barracuda |

| time_format | %H:%i:%s |

+---------------------------+-------------------+

3072字节除以 utf8mb4 的最大编码长度4字节,在主键字段上长度上限应该是768,测试如下:

[testdb]> create table t4(name varchar(769) primary key) charset=utf8mb4;

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

[testdb]> create table t4(name varchar(768) primary key) charset=utf8mb4;

Query OK, 0 rows affected (0.01 sec)

不出所料,769长度字段建表失败,768长度字段建表成功。

现在抛开索引长度的限制,再次测试:

[testdb]> create table t41(name varchar(16383) not null) charset=utf8mb4;

Query OK, 0 rows affected (0.02 sec)

建表成功!

基于以上理论和实验:

在utf8 编码字符集中,字符的最大编码长度是3字节,比如中文;所以如果 name作为主键,这个字段字符长度不能超过 3072/3=1024;

[testdb]> create table t3(name varchar(1025) primary key) charset=utf8;

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

[testdb]> create table t3(name varchar(1024) primary key) charset=utf8;

Query OK, 0 rows affected (0.01 sec)

在utf8 编码字符集环境中,如果不使用索引,基于验证上面的理论 65535/3= 21845:

[testdb]> create table t32(name varchar(21845) not null ) charset=utf8;

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

建表语句依然报错?因为 "VARCHAR values are stored as a 1-byte or 2-byte length prefix plus data."

存储空间字符串前缀需要占用2个字节,所以创建失败。

[testdb]> create table t32(name varchar(21844) not null ) charset=utf8;

Query OK, 0 rows affected (0.01 sec)

建表成功了!

结论:

在latin1 编码字符集中,VARCHAR 类型字段最多能存储65533 个字符;

在utf8 编码字符集中,VARCHAR 类型字段最多能存储21844 个字符;

在utf8mb4 编码字符集中,VARCHAR 类型字段最多能存储16383 个字符;

以上是关于VARCHAR 类型字段存储字符长度,行长度以及索引长度的限制的一个小试验!

不妥之处欢迎指正!

mysql5 varchar_MYSQL 5.7 VARCHAR 类型实验相关推荐

  1. mysql5.0varchar_MySQL中varchar类型在5.0.3后的变化

    1.mysql varchar类型变化: mysql 5.0.3 之前: 0--255字节 varchar(20)中的20表示字节数,如果存放urf8编码的话只能放6个汉字. MySQL 5.0.3 ...

  2. mysql where varchar_MySQL数据库之MySQL索引使用:字段为varchar类型时,条件要使用''包起来...

    本文主要向大家介绍了MySQL数据库之MySQL索引使用:字段为varchar类型时,条件要使用''包起来 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 结论: 当MySQL中 ...

  3. MySQL之char、varchar类型简析

    我们都知道,MySQL中关于字符,有char和varchar两种常用的类型,可能在平时的使用过程中,大家不会去关心这两种类型的区别,只是会用就可以了,或者说看到过一些它们的区别,但是没有时间去测试,今 ...

  4. MySql中的varchar类型

    1.varchar类型的变化 MySQL 数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255(根据不同版本数据库来定).在 MySQL5.0以 ...

  5. mysql varchar java_关于MySQL varchar类型最大值,原来一直都理解错了

    写在前面 关于MySQL varchar字段类型的最大值计算,也许我们一直都理解错误了,本文从问题出发,经实践验证得出一些实用经验,希望对大家的开发工作有些帮助~ 背景描述 最近同事在做技术方案设计时 ...

  6. MySql学习之varchar类型

    MySQL 数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255(根据不同版本数据库来定),在 MySQL5.0以上的版本中,varchar数据 ...

  7. mysql varchar 中英文_MySQL5.1中varchar类型中文和英文长度的问题

    今天,也是突发奇想,在MySQL上验证varchar(15)会存15个中文,超过的会自动截取前15个. 一直抱守旧的观念(这种观念可能来源与s 今天,也是突发奇想,在MySQL上验证varchar(1 ...

  8. 数据库中varchar类型 最大长度是多少?

    一. varchar存储规则: 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节)  5.0版本以上,varchar(20),指的是20字符, ...

  9. MySQL中对varchar类型排序问题的解决

    mysql数据库,把数值型的写成varchar类型 ,其实应该建为int的.因为我只允许输出数字.发现排序有问题.下面简单说一下MySQL的varchar排序问题. 下面,我从数据库里面以number ...

最新文章

  1. 深度学习面试必备的 25 个问题
  2. 佳能CANON LBP2900打印缓慢问题解决方法
  3. Java多线程2:Thread中的实例方法
  4. Oracle微服务框架 Helidon尝鲜(一)!~
  5. 8.3. 测试 opensips
  6. [存储过程]中的事务(rollback)回滚
  7. CoreData / MagicalRecord
  8. Lucene的索引不跨平台
  9. 所以,我们依然要读书
  10. Node.js视频教程
  11. android通过经纬度获取地址,android之location 根据接口获取经纬度信息
  12. jQuery暴打灰太狼小游戏
  13. eviews求相关系数
  14. 共享单车调度_原来共享单车是这样调度的
  15. 服务器系统2008r2企业版补丁,windows2008R2服务器更新补丁
  16. GIS应用技巧之景观格局分析(一)
  17. 手机怎样设置一个高考倒计时便签,可以天天看见那种
  18. php 正则保留数字和,只保留汉字,字母,数字正则
  19. Dubbo源码解析(九)Dubbo系列 源码总结+最近感悟
  20. Flink时间语义与watermark的原理

热门文章

  1. 15crmo焊接后多长时间探伤_承压设备渗透探伤检测方法简单操作思路
  2. angularjs1访问子组件_Vue学习笔记之组件的应用
  3. java perl5compiler,Java中正则表达式使用方法详解(四)
  4. JS文件信息收集工具-LinkFinder
  5. diff命令两个服务器文件,linux 比较两个文件夹不同 (diff命令, md5列表)
  6. 太和二中计算机考试,安徽省太和二中高二数学下册期末考试试题精选
  7. git提交代码时报错:nothing added to commit but untracked files present
  8. cf1207解题报告
  9. oracle用EXPLAIN PLAN 分析SQL语句
  10. [转]我是如何走进黑客世界的?