Mysql中char和varchar的区别详细剖析

本文对比了char和varchar在最大长度、定长、空间使用、查找效率及尾部空格上的差异,解析了为何char查询更快且浪费空间,同时介绍了它们在不同场景下的应用,如短信息存储、固定长度数据和频繁变更的column。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、区别

1、最大长度:

char最大长度是255个字符,varchar最大长度是65535个字符。

2、定长:

char是定长的,不足的部分会用隐藏空格填充,varchar是不定长的。
当向char中插入数据时,如果该数据小于定义的长度,那么就会用空格填充不足的部分;
当向varchar中插入数据时,如果数据小于定义的长度,那么按数据的实际长度存储,即插入多长就存多长;当要存储的数据的实际长度大于定义的长度时,会对该数据进行自动截取。也就是说varchar的动态存储体现在存储数据的实际长度小于所给它定义的长度时。

3、空间使用:

char会浪费空间,varchar会更加节省空间。

4、查找效率:

char查找效率会很高,varchar查找效率会更低。
因为char的长度固定,故char的存取速度还是要比varchar快得多,存储与查找会更加方便;但是char也为此付出了空间的代价,因为其长度固定,所以会占据多余的空间,可谓是以空间换取时间效率。varchar则刚好相反,是以时间换空间,存储与查找相比于char效率更低一些。

5、尾部空格:

char插入时可省略,vaechar插入时不会省略,但查找时省略。

二、char比varchar查询效率更快以及比varchar更浪费空间的原因

这是由他们在磁盘上存放的不同形式决定的,我们先来看一个图:
在这里插入图片描述
从图中我们可以明显发现存储相同的数据,char类型会比varchar类型更耗费空间。
char类型在存放数据的时候,中间是没有间隔的,数据本身是有空格的,但是数据段之间是没有间隔的,这是因为我们在创建列的时候已经告诉MySQL列的长度了,MySQL在查询数据的时候,只需要按部就班寻找就行了,不需要在中途计算这个数据段的长度。
但是varchar类型的存放就不同了,它是动态分配存储空间的,在每个数据段开头,都要有一段空间来(1~2个字节)存放数据段的长度信息,在数据段的结尾也还有一段空间(1个字节)标记此字段的节数。MySQL在读取一个数据段的时候,首先要读开头,比如读到了3,说明数据段的长度是3,之后就不多不少,只读3个字节,也只分配3个字节的存储空间。所以MySQL在遍历数据的时候,磁针要比char类型的列,多读很多次磁盘来获取字段的真实长度,这就是为什么varchar比char查询效率低的原因了。

三、常用场景

一,存储非常非常短的信息,比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占1个byte用于存储信息长度,本来varchar是用来节约存储空间的,但现在得不偿失。

二,固定长度的。更适合用char,比如使用uuid作为主键,那用char应该更合适。因为他固定长度,此时varchar动态根据长度的特性就相当于没有了,而且还要占1个长度信息。

三,十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要耗费很多的精力用于计算,而这些对于char来说是不需要的,所以这种场景下更适合用varchar。

<think>好的,我现在需要详细思考用户关于CHARVARCHAR区别的问题。用户之前已经询问过如何创建宿舍名单的SQL表结构,现在进一步探讨数据类型的选择,特别是CHARVARCHAR区别。这说明用户可能在设计数据库时遇到了存储效率或字段长度的问题,或者想更深入理解这两种数据类型的适用场景。 首先,我需要回忆CHARVARCHAR的基本定义。CHAR是定长字符串,无论实际数据长度如何,都会占用定义的长度空间。例如,CHAR(5)存储"abc"会占用5个字符的空间,剩余部分用空格填充。而VARCHAR是变长字符串,根据实际数据长度分配存储空间,外加额外的字节来记录长度。比如VARCHAR(5)存储"abc"只会占用3个字符的空间加上长度信息。 接下来,要比较两者的存储方式。CHAR由于是定长,可能会有空间浪费,但读取速度快,因为长度固定,便于预计算存储位置。VARCHAR节省空间,但可能会有额外的开销,因为需要存储长度信息,并且在修改数据时可能导致行溢出,影响性能。 适用场景方面,CHAR适合存储长度相对固定且较短的字符串,比如性别、国家代码等。而VARCHAR适合长度变化较大的数据,如用户名、地址等。需要提醒用户注意数据库系统的具体实现,比如在某些系统中,VARCHAR可能有最大长度限制,或者在处理非常短的字符串时,CHAR可能更高效。 用户之前的问题中,他们使用了CHAR(5)来存储姓名,这可能存在问题,因为中文姓名可能超过5个字符,比如复姓或较长的名字。建议改用VARCHAR并适当调整长度,比如VARCHAR(10)或更长的,以适应不同的情况。这也是之前回复中提到的优化点,所以需要保持一致性。 此外,需要注意不同数据库系统对CHARVARCHAR的处理可能略有不同,比如是否自动去除末尾空格,最大长度限制等。例如,MySQLVARCHAR最多可以存储65535字节,但实际长度还受行大小限制。而CHAR在存储时会填充空格,检索时会自动去除,这可能导致一些意想不到的行为,比如比较时忽略末尾空格。 还需要考虑性能方面。如果表中的列多数为定长数据,使用CHAR可以让整个表成为静态表,提高查询效率。反之,如果有很多变长字段,使用VARCHAR节省空间,但可能影响查询速度。在内存磁盘空间之间需要权衡。 可能用户没有考虑到字符集的影响,比如UTF-8下,每个字符可能占用多个字节,CHAR(5)可能会占用更多的存储空间。而VARCHAR在这种情况下,实际存储的字节数会根据字符而变化,更加灵活。 最后,需要以清晰的结构将这些点整理出来,确保用户能够逐步理解两者的区别,并应用到实际数据库设计中。同时,结合之前的例子,说明为何在姓名字段中使用VARCHAR更合适,加强用户的理解。</think>以下是关于 **CHAR** **VARCHAR** 数据类型详细对比分析: --- ### 一、核心区别总结 | **特性** | **CHAR** | **VARCHAR** | |----------------|-----------------------------------|---------------------------------| | **存储方式** | 定长字符串(固定分配空间) | 变长字符串(按需分配空间) | | **空格处理** | 自动填充空格至定义长度 | 不填充,保留原始长度 | | **存储效率** | 可能浪费空间(短数据时) | 更节省空间(适应不同长度) | | **查询速度** | 较快(长度固定,无需计算) | 稍慢(需读取长度信息) | | **适用场景** | 长度固定的短字符串(如编码、标志) | 长度变化较大的字符串(如描述、名称) | --- ### 二、存储机制详解 1. **CHAR** - 定义示例:`CHAR(5)` - 存储行为: - 存入"abc" ➔ 实际存储为`'abc '`(补2个空格) - 始终占用**5个字符**的存储空间 - 特点: - 读取时自动去除末尾空格 - 比较操作忽略末尾空格(`'a' = 'a '`返回`True`) 2. **VARCHAR** - 定义示例:`VARCHAR(5)` - 存储行为: - 存入"abc" ➔ 实际存储`'abc'`(占用3字符 + 长度信息1-2字节) - 最大占用空间 = 定义长度 + 额外长度标识(通常1-2字节) - 特点: - 保留所有空格(包括末尾) - 比较操作严格区分空格(`'a' ≠ 'a '`) --- ### 三、性能空间对比 - **空间效率**(假设字段定义为`CHAR(10)` vs `VARCHAR(10)`): | 输入值 | CHAR占用空间 | VARCHAR占用空间 | |-------------|-------------|-----------------| | "Hi" | 10字节 | 2字节 + 1字节长度标识 = **3字节** | | "Hello" | 10字节 | 5字节 + 1字节长度标识 = **6字节** | | "HelloWorld"| 10字节(截断)| 10字节 + 1字节长度标识 = **11字节**(若允许存储) | - **性能影响**: - `CHAR`在频繁查询的固定长度字段中更快(如状态码、性别) - `VARCHAR`在大文本或长度变化大的字段中更高效(如评论、地址) --- ### 四、使用场景建议 1. **优先使用 CHAR** - 字段值长度**完全固定**(如:`性别 ENUM('男','女')`) - 字段值**短且频繁查询**(如:`国家代码 CHAR(2)`) 2. **优先使用 VARCHAR** - 字段值长度**变化较大**(如:`姓名 VARCHAR(20)`) - 需要**节省存储空间**(如:长文本描述`VARCHAR(255)`) - 包含**末尾空格需保留**的场景(如:密码字段) --- ### 五、实际案例演示 ```sql -- 示例表 CREATE TABLE test ( fixed_code CHAR(3), -- 定长编码(如"CN"/"US") dynamic_desc VARCHAR(50) -- 变长描述 ); -- 插入数据 INSERT INTO test VALUES ('CN', '中国北京市'), ('US', '美国加利福尼亚州'); -- 查询结果 SELECT fixed_code, LENGTH(fixed_code) AS char_length, -- 始终返回3 LENGTH(dynamic_desc) AS varchar_length -- 返回实际长度 FROM test; ``` --- ### 六、注意事项 1. **字符集影响**: - UTF-8等变长编码下,`CHAR(n)`实际存储空间可能超过`n`字节(如中文占3字节/字符) 2. **数据库兼容性**: - 某些数据库(如Oracle)用`VARCHAR2`替代`VARCHAR`,需注意语法差异 3. **设计原则**: - 避免过度使用`CHAR`导致存储浪费 - `VARCHAR`最大长度需根据业务需求合理设定(如`VARCHAR(255)`是常见选择)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值