MySQL之char、varchar类型简析

简介: MySQL之char、varchar类型简析

我们都知道,MySQL中关于字符,有char和varchar两种常用的类型,可能在平时的使用过程中,大家不会去关心这两种类型的区别,只是会用就可以了,或者说看到过一些它们的区别,但是没有时间去测试,今天有时间了,我将这两种类型的具体情况实验一把,让大家直观感受下,纯属分享,大神请绕道。


先说说理论吧。


char类型为固定长度的字符串,比如说char(10),它定义了指定的字符串长度最大为10个字符,如果你现在输入一个字符串为’12345678’,那么它在char类型中到底会占用多少个字符呢?答案是10个,后面缺少的2个字符,MySQL会自动补充为空值,然后进行存放。在取这个记录的时候,char类型的会使用trim()函数去掉多余的空格,所以我们看到的还是8个字符的记录。当输入的字符长度大于最大的长度时,MySQL会自动报错。


varchar类型是长度可变的字符串,varchar(M)表示最大长度是M个字符,varchar的最大实际长度由最大的行的大小和使用的字符集确定。例如varchar(50)定义了一个最大长度为50的字符串,如果插入的字符串只有20个字符,那么实际存储的字符串具有21个字符,因为varchar会自动包含一个字符串结束字符。varchar在值保存和检索时,尾部的空格仍然保留。


介绍完概念,我们来看具体的实践过程,本文中使用的测试版本为MySQL5.7.22版本。


1.测试char的trim()功能


首先创建一个表,这个表里面包含两个字段,d_char和d_varchar,设定初始的字符长度都为4,如下:


image.png


查看一下,


image.png


此时,我们插入两条记录,每条记录都是’ab ',注意,ab后面有2个空格,


image.png


然后我们使用mysql里面的concat函数进行字符连接,给每条记录的左右分别添加小括号,


image.png


此时我们可以看到,d_char的ab后面的空格被取消掉了,而d_varchar后面的空格还依旧存在。


2.测试两种字符类型的最大长度


首先看看char的最大长度,我们设置的值为256,结果如下


image.png


所以,char类型的长度取值范围为0~255个字符


上面提到了varchar的最大实际长度由最大的行的大小和使用的字符集确定,这里我们进行实验:


image.png


可以看到,字符集不一样,最后的max的值也是不一样的,


utf8模式下是0~21845,一个字符占三个字节,最多能存 21844 个字符


latin1模式下是0~65535,一个字符占一个字节,最多能存放 65532 个字符


gbk模式下是0~32767,一个字符占两个字节,最多能存 32766 个字符


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


可能这里有人要问了,为什么最大值是32767,而最多只能放32766个字符呢?


举两个例说明一下实际长度的计算。


a) 若一个表只有一个varchar类型,如定义为


create table t4(c varchar(N)) charset=gbk;


则此处N的最大值为(65535-1-2)/2= 32766 个字符。


减1的原因是实际行存储从第二个字节开始’;


减2的原因是varchar头部的2个字节表示长度;


除2的原因是字符编码是gbk。


b) 若一个表定义为


create table t4(c int, c2 char(30), c3 varchar(N)) charset=utf8;


则此处N的最大值为 (65535-1-2-4-30*3)/3=21812


减1和减2与上例相同;


减4的原因是int类型的c占4个字节;


减30*3的原因是char(30)占用90个字节,编码是utf8。


如果被varchar超过上述的b规则,被强转成text类型,则每个字段占用定义长度为11字节,当然这已经不是“varchar”了。


则此处N的最大值为 (65535-1-2-4-30*3)/3=21812


3.MySQL的字段长度模式


字段长度的模式分为严格模式和不严格模式,在严格模式下,如果我们想给一个字段中插入一个大于规定长度的字符串,MySQL会给出错误提示,例如我们的表:


image.png


当我们插入一个大于4字符的记录时,


image.png


如果在非严格模式下,mysql会自动截断超出最大长度的字符,


image.png


上面的操作是,我们先把字段模式改为非严格模式,然后查询更改,确保更改生效,接着我们插入’abcde’字符串,发现它可以被成功执行,但是包含两个警告,查看警告可以发现,一些数据被截断了,


image.png


实验部分的内容基本就完成了,这里我们进行几点分析:


1.MySQL为什么要设置这两种类型?它们各自有什么优点?


char是固定长度的,它的存取速度比varchar快,方便程序的存储于查找,但是它需要浪费一定的空间,可以看做是一种以空间换时间的方法。


而varchar的特点是可变长,当定义一个varchar(10)而只存入了4个字符,此时varchar会直接将字符记录的长度变为4,从而节省空间,它可以看做是一种用时间换取空间的方法。


char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode的字符数据。


2.两种类型适应的情况分析。


关于char:


CHAR适合存储很短的字符串,或者所有值都接近同一个长度。


对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。


对于非常短的列,CHAR在存储空间上也更有效率。例如用char(1)来存储只有Y和N的值,只需要一个字节,但是varchar却需要两个字节,因为还一个记录长度的额外字节。


关于varchar


VARCHAR类型用于存储可变长字符串,是最常见的字符串数据类型。它比定长类型 更节省空间,因为它仅使用必要的空间(例如,越短的字符串使用越少的空间)。


VARCHAR节省了存储空间,所以对性能也有帮助。但是,由于行是变长的,在UPDATE时可能使行变得比原来更长,这就导致需要做额外的工作。如果一个行占用 的空间增长,并且在页内没有更多的空间可以存储,在这种情况下,不同的存储引擎的处理方式是不一样的。例如,MyISAM会将行拆成不同的片段存储,InnoDB 则需要分裂页来使行可以放进页内。


VARCHAR需要使用1或2个额外字节记录字符串的长度:如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节。假设采用latinl字符集 ,一个varchar(10)的列需要11个字节的存储空间。varchar(1000)的列则需要1002个字节,因为需要2个字节存储长度信息。


适用情况:


1、对于MyISAM表,尽量使用Char,对于那些经常需要修改而容易形成碎片的myisam和isam数据表就更是如此,它的缺点就是占用磁盘空间;


2、对于InnoDB表,因为它的数据行内部存储格式对固定长度的数据行和可变长度的数据行不加区分(所有数据行共用一个表头部分,这个标头部分存放着指向各有关数据列的指针),所以使用char类型不见得会比使用varchar类型好。事实上,因为char类型通常要比varchar类型占用更多的空间,所以从减少空间占用量和减少磁盘i/o的角度,使用varchar类型反而更有利;


3、存储很短的信息,比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的现在得不偿失。


4、固定长度的。比如使用uuid作为主键,那用char应该更合适。因为他固定长度,varchar动态根据长度的特性就消失了,而且还要占个长度信息。


5、十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。


关于MySQL之char、varchar,你学废了么?

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
9月前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
10月前
|
SQL
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**问题简介:** 客户在使用触发器将表 A 中 varchar(4000 char) 列的数据复制到表 B 时,发现表 B 中的数据出现乱码且与表 A 不一致。此问题影响所有 YashanDB 版本,原因是 YashanDB 在处理触发器场景下的大长度 varchar 数据复制时存在机制错误。为避免该问题,建议将列长度修改为 varchar(2000 char) 或更小。数据正确性无法保证,需谨慎处理。 **验证方法:** 可通过创建表 A 和 B 及相应触发器进行测试。
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
|
9月前
|
关系型数据库 MySQL Java
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
【YashanDB知识库】崖山BIT类型对MYSQL兼容问题
|
9月前
|
自然语言处理 关系型数据库 MySQL
MySQL索引有哪些类型?
● 普通索引:最基本的索引,没有任何限制。 ● 唯一索引:索引列的值必须唯一,但可以有空值。可以创建组合索引,则列值的组合必须唯一。 ● 主键索引:是特殊的唯一索引,不可以有空值,且表中只存在一个该值。 ● 组合索引:多列值组成一个索引,用于组合搜索,效率高于索引合并。 ● 全文索引:对文本的内容进行分词,进行搜索。
|
9月前
|
SQL
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
【YashanDB知识库】通过触发器复制varchar(4000 char)列的数据导致乱码
|
10月前
|
SQL
【YashanDB 知识库】通过触发器复制 varchar(4000 char) 列的数据导致乱码
**简介:** 某客户在使用触发器将表 A 的 varchar(4000 char) 列数据复制到表 B 时,出现数据乱码且不一致的问题。经分析,YashanDB 在处理触发器场景下的 varchar(4000 char) 列数据复制时存在机制错误,影响所有版本。建议将列长度修改为 varchar(2000 char) 或更小以规避问题。通过特定 SQL 可验证该问题是否存在。
|
10月前
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
|
存储 关系型数据库 MySQL
面试时被这样一个问:”存储MD5值应该用VARCHAR还是用CHAR?
一个5年工作经验的小伙伴,在面试的时候被这样一个问题。说”存储MD5值应该用VARCHAR还是用CHAR“,他一时间不只如何选择,感觉用VARCHAR也可以,用CHAR也行。希望我来帮忙分析一下。
289 0
|
存储 SQL 数据库
char、varchar、nvarchar、text的区别
char、varchar、nvarchar、text的区别
350 0
|
存储 关系型数据库 MySQL
MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%🚀
本篇文章来讨论MySQL字段的字符类型选择并深入实践char与varchar类型的区别以及在千万数据下的性能测试
MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%🚀

推荐镜像

更多