varcahr(255)是什么含义?

varchar(255) 表示可以存储最大255个字符,至于占多少个字节由字符集决定。

varchar的最大值是多少?

如果你去搜索过这个答案,我相信你或多或少都看到过65535这个答案。比如我们尝试询问一下当下最火的人工智能,你可能会得到和我类似答案。


那么varchar的最大值真的是65535吗?我们不妨实验一下。

create table test(
 test_varchar_max varchar(65535) not null default '' comment '测试varchar最大值'
) engine=innodb default charset=utf8mb4;

可以看到,mysql已经给我们提示错误了,而且已经提示了最大值是16383,怎么和我们想的不一样?那么varchar的最大值就是16383吗?接着看

create table test(
 test_varchar_max varchar(65535) not null default '' comment '测试varchar最大值'
) engine=innodb default charset=utf8;

可以看到这次的提示又不一样了,那么varchar的最大值到底是多少呢?

再回答这个问题之前,我们还需要先了解几个概念。

字符集

细心的小伙伴已经发现了,上面我们两个建表语句只有一处不一样,那就是charset的值不一样。其实charset就是设置表的字符集。

什么是字符集?看看百科给出的解释

字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,就需要进行字符编码,以便计算机能够识别和存储各种文字。中文文字数目大,而且还分为简体中文和繁体中文两种不同书写规则的文字,而计算机最初是按英语单字节字符设计的,因此,对中文字符进行编码,是中文信息交流的技术基础。

根据上面的实验,我们可以证明不同的字符集,因为对字符的编码规则不一样,所以占用存储大小也不一样。

那么mysql支持哪些字符集,而每种字符集占用多大空间呢?我们可以通过 show charset;查看,结果如下


那我们怎么才能知道这个最大长度是多少呢?还记得我们在上一个环节测试字符集错误提示varchar的最大长度吗?我们用那个长度 * 字符集的Maxlen 是不是就是varchar的最大值吗?我们用上面的测试结果算算看

utf8mb4 的 Maxlen = 4 对应 varchar的最大值为 4 * 16383 = 65532
utf8 的 Maxlen = 3 对应 varchar的最大值为 3 * 21845 = 65535

咦!怎么utf8mb4和utf8算出来的结果对应不上呢?我们再找一个gbk字符集测试一下呢。


gbk 的 Maxlen = 2 对应 varchar的最大值为 2 * 32767 = 65534

这下彻底对不上了,那怎么办呢?其实去测试过的小伙伴现在应该已经发现问题了,虽然utf8和gbk错误提示了一个Max值,但是你尝试设置为这个值的时候,你会发现会报错,只能设置为比提示小1的值。看测试




那我们根据最新能成功的实际最大值再计算一下varchar对应的最大值呢。

utf8mb4 的 Maxlen = 4 对应 varchar的最大值为 4 * 16383 = 65532
utf8 的 Maxlen = 3 对应 varchar的最大值为 3 * 21844 = 65532
gbk 的 Maxlen = 2 对应 varchar的最大值为 2 * 32766 = 65532

那你是不是就以为varchar的最大值就是65532「字节」了?先说答案,肯定是错!!!

null or not null?

上面的测试基本上证明了varchar可以存储65532字节的数据。不知道大家有没有发现,上面测试的字符集的Maxlen都是大于1的,有没有可能65532是因为刚好是上面几种字符集Maxlen的整数倍呢?

要验证这个问题,其实很简单。我们找一个字符集的Maxlen是1的测试一下不就知道了吗?


可以看到,latin字符集的varchar可以设置为65533,也就是varchar的最大字节是65533 * 1 = 65533。那么varchar的最大值真的就是65533字节了吗?

大家仔细看我们的建表SQL,你就会发现两点规律。

  1. 字段指定为了非空,也就是not null
  2. 整张表只有一个字段

那not null对varchar的最大值有影响吗?既然这么问了肯定是有影响的,实践是检验真理的唯一标准。上测试


测试证明,当字段设置为not null的时候,varchar可以最大存储65533字节的内容。而字段设置为允许为null的时候,最大可以存储65532字节的内容。

这是因为Innodb需要单独使用一个字节来存储允许为Null的字段。

多字段的影响

上面讲了为Null会对varchar的最大值有影响,其实表的字段数量也对varchar的最大值有影响。带大家回顾一下,mysql的错误提示

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

这里有两个重要信息,一个是所用表类型(不包括BLOB)的最大行大小为65535,还有一个就是这里面还包括存储开销。

其实从这里面我们不难看出,65535是一行数据的(不包括BLOB)最大字节数量,那如果我们一行有多个字段呢。


上面测试我们加如了一个int类型的字段,然后就发现原本能存储16383个utf8mb4字符,现在只能存储16382个utf8mb4字符了。那是因为一个int在Innodb中占4个字节,所以varchar就只能少一个字符了。字符数对应为 (行最大字节数 - int字段字节数)/ Maxlen = (65532 - 4)/ 4 = 16382。


再次证明,65532是行的最大字节数,而非varchar的最大字节数。

而提示的65535字节是包含其他开销的,所以其他开销就占65535 - 65533 = 2个字节。这里为什么是65533,因为Maxlen为1的字符集最大是65533,65532是字符集Maxlen的整数倍最接近65533的值。

那么回到最初的问题,varchar到底最大能存储多少字符?其实varchar能存储多大字符取决于两点,表字段有多少,是否可以为null。在不允许为null 且只有一个varchar字段的话,那最大能存储的字符数就等于65533 / Maxlen;

根据Innodb的规定,如果表字段包含变长字段varchar,需要额外用两个字节来存储varcahr的长度。为什么是两个字节?因为极限情况下就是表只有一个不允许为null的varchar字段,把么这个字段的长度就最大为65533个字节,那么就至少需要两个字节才能存下这个长度。2byte=16bit=2^16=65536,所以需要两个字节存储长度。

本文使用 markdown.com.cn 排版

MySQL varchar详解的更多相关文章

  1. MySQL 数据类型 详解

    MySQL 数据类型 详解 MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小的数据,并且 My ...

  2. mysql存储过程详解

    mysql存储过程详解 1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...

  3. mysql 存储过程详解 存储过程

    mysql存储过程详解 1.      存储过程简介         我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成 ...

  4. MySQL存储过程详解 mysql 存储过程

    原文地址:MySQL存储过程详解  mysql 存储过程作者:王者佳暮 mysql存储过程详解 1.     存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储 ...

  5. MySQL存储过程详解 mysql 存储过程(二)

    mysql存储过程详解 1.      存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL ...

  6. MySQL 操作详解

    MySQL 操作详解 一.实验简介 本节实验中学习并实践 MySQL 上创建数据库.创建表.查找信息等详细的语法及参数使用方法. 二.创建并使用数据库 1. 创建并选择数据库 使用SHOW语句找出服务 ...

  7. MySQL字符集详解

    Reference:  https://www.cnblogs.com/wcwen1990/p/6917109.html MySQL字符集详解   一.字符集和校验规则 字符集是一套符合和编码,校验规 ...

  8. (转)mysql explain详解

    原文:http://www.cnblogs.com/xuanzhi201111/p/4175635.html http://yutonger.com/18.html http://www.jiansh ...

  9. MySQL存储过程详解 mysql 存储过程(转)

    mysql存储过程详解 1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...

  10. mysql存储过程详解实例

    mysql存储过程详解 1.      存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL ...

随机推荐

  1. Hive分区和分桶的区别

    1.前言 Hive的分区和分桶都是细化数据管理,加快数据查询和分析,两者有什么区别呢?下面讲解一下分区和分桶的原理. 2.分区 (1)分区原理 Hive的分区表可以有一个或多个分区键,用于确定数据的存 ...

  2. MySQL最左匹配原则

    最左匹配原则都是针对联合索引来说的,那么为什么要使用联合索引呢? 一.为什么要使用联合索引? 1.减少开销. 建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,c ...

  3. JS 疫情宅在家,学习不能停,七千字长文助你彻底弄懂原型与原型链,武汉加油!!中国加油!!(破音)

    壹 ❀ 引 原型与原型链属于老生常谈的问题,也是面试高频问题,但对于很多前端开发者来说,组织语言去解释清楚是较为困难的事情,并不是原型有多难,稍微了解的同学都知道原型这一块涉及太多知识.比如我们可以灵 ...

  4. NC201985 立方数

    题目链接 题目 题目描述 对于给定的正整数 N,求最大的正整数 A,使得存在正整数 B,满足 \(A^3B=N\) 输入包含 T 组数据,1≤T≤10,000:\(1≤N≤10^{18}\) 输入描述 ...

  5. python 中记录dmesg信息并进行分析的方法(@)

    在Python中记录系统的dmesg 信息,并进行分析的方法简述: 基本命令: dmesg -C 清除之前的dmesg  信息: dmesg -T > testExample.msg      ...

  6. Laravel入坑指南(12)——最终章:Session、缓存与Redis

    因为web服务除了业务准确之外,我们最关注的就是服务的性能.鉴于web服务几乎都是IO密集型,我们为了提高IO的速度,自然不能把所有的数据都放在关系型数据库中.而redis的并发与性能可以很好地帮我们 ...

  7. Java并发编程实例--15.在同步代码块中使用条件

    并发编程中有个经典问题: 生产消费者问题. 我们有一个数据缓冲区,一个或多个生产者往其中存入对象,另外一个或多个消费者从中取走. 因此,该数据缓冲区是一个共享数据结构,我们需要对其添加读取同步机制,但 ...

  8. golang中的接口(数据类型)

    golang中的接口 Golang 中的接口是一种抽象数据类型,Golang 中接口定义了对象的行为规范,只定义规范 不实现.接口中定义的规范由具体的对象来实现,通俗的讲接口就一个标准,它是对一个对象 ...

  9. c2工具sliver的python客户端无法修改grpc超时时间的解决办法

    业务需要,调用了很多implants来执行对应系统上的命令, 但是无论怎么指定interactive.py中execute方法参数, 命令执行超时时间总是30. 后面通过扩展execute方法增加一个 ...

  10. [攻防世界][Web]PHP2

    打开靶机对应的url 就一行字 Can you anthenticate to this website? 第一感觉就需要做目录文件扫描 使用御剑和dirsearch进行扫描,发现一个文件 index ...