MySQL char 和 varchar 的区别是什么?
2026年01月04日
一则或许对你有用的小广告
欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于
Spring AI + Spring Boot3.x + JDK 21..., 点击查看; - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot3.x + JDK 17..., 点击查看项目介绍; 演示链接: http://116.62.199.48:7070/; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
面试考察点
面试官提出这个问题,不仅仅是希望你记住两种数据类型的定义,更是为了考察:
- 基础概念理解:是否清楚
CHAR和VARCHAR最核心的 “定长” 与 “变长” 区别。 - 存储机制掌握:是否了解 MySQL 底层如何存储这两种类型的数据,这关系到对 存储空间、I/O 性能 的理解。
- 实际应用能力:能否根据具体的业务场景(例如存储固定长度的身份证号、或长度多变的用户昵称)做出正确的类型选择,这体现了设计表时的 实践经验和性能考量。
- 细节关注度:是否了解一些关键细节,例如
VARCHAR的长度限制(65535 字节)、不同字符集(如 utf8mb4)下的实际字符数限制,以及CHAR在存储时会去除尾部空格等行为。
核心答案
CHAR 和 VARCHAR 是 MySQL 中最常用的两种字符串类型,其核心区别在于 存储方式:
CHAR(N)是 定长字符串。无论实际存储的字符串多长(即使只存了1个字符),它都会固定占用 N 个字符的存储空间。如果不足,会用空格在尾部填充。VARCHAR(N)是 变长字符串。它只会占用实际字符串长度 + 额外长度标识的存储空间。这个 “额外长度” 用于记录字符串有多长。
因此,对于长度固定或波动极小的数据(如国家代码 CHAR(2), MD5 哈希值 CHAR(32)),使用 CHAR 更高效。对于长度变化大的数据(如用户名、文章标题),使用 VARCHAR 能显著节省存储空间。
深度解析
原理/机制
CHAR的存储:- 分配固定的 N 个字符宽度。
- 存储时,如果数据长度小于 N,会在右侧用空格填充到指定长度。
- 检索时,会自动去除尾部填充的空格(但在比较时,空格处理有细微差别,依赖于
PAD_CHAR_TO_FULL_LENGTHSQL Mode)。
VARCHAR的存储:- 采用“长度前缀 + 实际数据”的紧凑格式。
- 如果长度 <= 255 字节,前缀用 1 个字节 表示;否则用 2 个字节。这就是为什么
VARCHAR(255)是一个常见的设计节点。 - 存储的是精确的字符串内容,不会填充空格。
代码示例
以下 SQL 示例清晰地展示了行为差异:
-- 创建测试表
CREATE TABLE test_string (
col_char CHAR(10),
col_varchar VARCHAR(10)
);
-- 插入相同数据
INSERT INTO test_string VALUES ('abc', 'abc');
-- 查询数据长度(注意CHAR类型的返回值)
SELECT
col_char,
CHAR_LENGTH(col_char) as char_len, -- 结果为 3,因为检索时去除了尾部空格
col_varchar,
CHAR_LENGTH(col_varchar) as varchar_len -- 结果为 3
FROM test_string;
-- 验证存储空间占用(近似方法,不同引擎有差异)
-- 对于 ‘abc’:
-- col_char 固定占用 10 字符(例如 utf8mb4 下为 10*4=40 字节)
-- col_varchar 占用 3字符 + 1字节长度前缀 = 13 字节(utf8mb4)
对比分析与最佳实践
| 维度 | CHAR(N) | VARCHAR(N) |
|---|---|---|
| 本质 | 定长 | 变长 |
| 存储空间 | 固定 N * 字符集最大字节长度。存储短字符串时有空间浪费。 | 实际字符数 * 字符集字节数 + 长度前缀(1或2字节)。更节省空间。 |
| 存取速度 | 理论上更快。因为是固定长度,磁盘寻址和内存计算更简单。 | 稍慢。需要根据长度前缀计算实际位置,但在现代硬件下差异很小。 |
| 尾部空格 | 存入时填充,检索时自动去除(比较时需注意)。 | 原样存储和检索,不会去除。 |
| 适用场景 | 长度固定或几乎不变的数据: • 枚举代码(如性别 M/F)• 固定长度的哈希值(MD5, UUID) • 邮编、国家代码 | 长度变化较大的数据: • 用户名、邮箱地址 • 文章标题、摘要 • 任何无法确定长度的文本字段 |
最佳实践建议:
- 优先使用
VARCHAR:在绝大多数业务场景中,字符串长度都是可变的,使用VARCHAR是最佳选择,能有效节省存储,尤其是表数据量巨大时。 - 明确使用
CHAR的场景:只有当你百分之百确定该字段长度绝对固定时,才使用CHAR。例如CHAR(32)存储 MD5 值。 - 关于长度
N的设置:VARCHAR(N)的N指的是最大字符数,而非字节数。在utf8mb4字符集(每个字符最多占 4 字节)下,一个VARCHAR(255)字段理论最大占用约255 * 4 + 2 = 1022字节。
常见误区
- 误区一:“
CHAR一定比VARCHAR快”:这个结论在小表或简单查询中不明显。VARCHAR的紧凑存储减少了磁盘 I/O,有时反而更具优势。性能差异应通过实际压测判断。 - 误区二:“
VARCHAR最大长度就是 65535”:这是最大字节数限制。一个VARCHAR列的实际最大字符数受限于所选字符集。例如在utf8mb4下,单列最大字符数约为(65535 - 2) / 4 ≈ 16383。 - 误区三:过度放大类型选择的影响:在早期架构设计和 SQL 优化中,关注点应优先放在索引设计、查询语句、范式与反范式上。在确认这些是瓶颈后,再考虑此类微观优化。
总结
简单来说,CHAR 是“用空间换时间”的定长类型,适合存储长度绝对固定的字典码;而 VARCHAR 是“用计算换空间”的变长类型,适合存储长度不确定的通用文本,这也是现代数据库设计中更主流和推荐的选择。