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. 启动T0运行的C语言语句是,单片机填空题期末复习。、
  2. hbase 的shell操作中相关属性说明
  3. layuiadmin上手好难_孩子学什么乐器好?十种最受欢迎乐器的优劣势分析
  4. PyTorch(CNN+MNIST测试)
  5. mysql报错无效默认值1067_Mysql 报错:#1067
  6. Java计算机毕业设计德云社票务系统源码+系统+数据库+lw文档
  7. java课题研究方法和技术途径_课题研究的基本方法有哪些?
  8. 腾讯cdn设置 php,WordPress使用腾讯云CDN配置教程(https)
  9. 中软酒店管理系统CSHIS操作手册_数据结构_数据字典
  10. SwiftUI iOS 开源组件之银行卡切换效果 (教程含源码)
  11. Unity 性能优化基础
  12. 初夏,开源魔改一个带击杀音效的电蚊拍!
  13. norflash/nandflash 启动分析
  14. Windows Server 2012修改光驱盘符
  15. 数据库原理与应用--数据库系统概述
  16. Linux ALSA声卡驱动之五:Machine 以及ALSA声卡的注册
  17. js 实现多物体动画效果
  18. std:weak_ptr
  19. java.lang.IllegalArgumentException的解决方法
  20. 判断iPhone 硬件设备型号

热门文章

  1. 蓝桥杯 2011年第二届C语言初赛试题(3)
  2. ajax servlet增删改查,Servlet ajax 文件上传和JDBC+Servler用户表增删改查
  3. python倒排索引实现_倒排索引原理和实现 - uncle_LLD的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. Postman安装与使用(网络请求神器)--post、get请求
  5. 仅使用HTML和CSS实现的标签云效果
  6. 计算机的iscsi配置,PC端的iSCSI参数设置方法
  7. java开发一款坦克大战游戏
  8. Linux的shell编写
  9. burpsuite全套使用教程
  10. 你不懂js系列学习笔记-异步与性能- 02