CHAR、VARCHAR、TEXT 的差别与存储方式
文章目录
- 《CHAR、VARCHAR、TEXT 的差别与存储方式》
- 一、前言:为什么要深入理解字符串类型
- 二、CHAR 与 VARCHAR 的定义与核心区别
- 三、CHAR 的存储原理
- (1)定长存储方式
- (2)检索自动去空格
- (3)优点与缺点
- 四、VARCHAR 的存储原理
- (1)变长结构
- (2)存储示例
- (3)优点与缺点
- 五、TEXT 类型的特殊性
- (1)种类与长度上限
- (2)存储方式
- (3)注意事项
- 六、性能与内存差异分析
- 七、实际项目中的使用建议
- 八、面试高频问题与答题模板
- 九、总结
《CHAR、VARCHAR、TEXT 的差别与存储方式》
一、前言:为什么要深入理解字符串类型
大家好,我是程序员卷卷狗。
在 MySQL 中,字符串类型的选择是设计表结构时的关键决策之一。
同样是存储文本,为什么有的人用 CHAR,有的人用 VARCHAR,还有人选择 TEXT?
这并不只是“定长 vs 变长”的问题。
它关乎:
- 空间占用;
- 查询性能;
- 是否能使用索引;
- 是否支持内存临时表。
掌握底层区别,才能真正写出“性能友好”的表结构。
二、CHAR 与 VARCHAR 的定义与核心区别
| 特性 | CHAR(n) | VARCHAR(n) |
|---|---|---|
| 存储类型 | 定长 | 变长 |
| 占用空间 | 固定 n 字节(不足补空格) | 实际长度 + 1~2 字节长度信息 |
| 最大长度 | 255 字节 | 65535 字节(受行限制) |
| 存储效率 | 写入快 | 空间利用高 |
| 查询性能 | 稳定(不需动态长度计算) | 读时需解析长度信息 |
| 适用场景 | 固定长度字段(如手机号、身份证) | 长度变化字段(如昵称、地址) |
一句话总结:
CHAR 追求稳定与速度,VARCHAR 追求灵活与节省空间。
三、CHAR 的存储原理
(1)定长存储方式
无论实际内容长度是多少,都会按定义长度 n 存储。
不足的部分用 空格(Space)填充。
CREATE TABLE t1 (code CHAR(10)
);
INSERT INTO t1 VALUES ('A');
实际存储长度:10 字节。
(2)检索自动去空格
查询时,MySQL 会自动去掉补空格:
SELECT code='A' FROM t1; -- 返回 TRUE
(3)优点与缺点
- 优点:无需动态长度计算,I/O 访问更快;
- 缺点:浪费空间,尤其是大批量短字段场景。
适合场景: 固定长度数据,如国家代码、性别、身份证号等。
四、VARCHAR 的存储原理
(1)变长结构
VARCHAR 在存储时包含两部分:
[长度信息][真实数据]
-
长度信息:占 1 或 2 个字节;
- 若最大长度 ≤ 255,用 1 字节;
- 否则用 2 字节;
-
真实数据:按实际长度存储。
(2)存储示例
CREATE TABLE t2 (name VARCHAR(10)
);
INSERT INTO t2 VALUES ('AB');
实际存储:[0x02]['A']['B'],共 3 字节。
(3)优点与缺点
- 优点:节省存储空间;
- 缺点:每次读写需计算长度,CPU 开销略大。
适合场景: 字段长度不确定但上限可控,如邮箱、昵称、备注。
五、TEXT 类型的特殊性
TEXT 属于 大字段类型(LOB, Large Object),
用于存储超大文本,如文章内容、日志、描述字段。
(1)种类与长度上限
| 类型 | 最大长度 |
|---|---|
| TINYTEXT | 255 字节 |
| TEXT | 65,535 字节(约64KB) |
| MEDIUMTEXT | 16,777,215 字节(约16MB) |
| LONGTEXT | 4,294,967,295 字节(约4GB) |
(2)存储方式
InnoDB 默认行格式下(COMPACT 或 DYNAMIC):
- TEXT 超出阈值时,会将部分数据存储在 溢出页(Off-page);
- 主记录只保存指针(20 字节);
- 每次访问 TEXT 字段需要额外 I/O。
结构示意:
┌──────────────┐
│ 主记录页 │
│ id=1 │
│ text_ptr -> │────┐
└──────────────┘ │▼┌────────────┐│ 溢出页数据 ││ 大文本内容 │└────────────┘
(3)注意事项
-
TEXT 不能有默认值;
-
TEXT 字段无法完整使用索引,只能建立前缀索引:
CREATE INDEX idx_content ON article(content(100)); -
排序、分组时常会触发临时磁盘表,性能较低。
适合场景: 存储大文本内容,如博客正文、商品描述等。
六、性能与内存差异分析
| 对比项 | CHAR | VARCHAR | TEXT |
|---|---|---|---|
| 存储长度 | 固定 | 变长 | 超大变长 |
| 空间效率 | 低 | 高 | 低(含页外存储) |
| 查询速度 | 快 | 稍慢 | 慢(需页外读取) |
| 是否可索引 | 全字段 | 全字段 | 仅前缀 |
| 是否支持默认值 | ✅ | ✅ | ❌ |
| 适用场景 | 固定长度字段 | 可变字段 | 超长文本 |
七、实际项目中的使用建议
| 业务场景 | 推荐类型 | 理由 |
|---|---|---|
| 手机号、身份证号 | CHAR(11/18) | 固定长度、查询高效 |
| 用户昵称 | VARCHAR(50) | 长度不固定,节省空间 |
| 邮箱地址 | VARCHAR(100) | 变长字段 |
| 商品描述 | TEXT | 内容长、变动大 |
| 系统日志 | MEDIUMTEXT | 长文本场景 |
| 配置信息 | VARCHAR + JSON | 更结构化、可索引 |
优化建议:
- 小文本尽量避免 TEXT;
- TEXT 查询需慎用模糊匹配;
- 可结合 Elasticsearch 存储长文本以提升检索性能。
八、面试高频问题与答题模板
| 问题 | 答案要点 |
|---|---|
| Q1:CHAR 和 VARCHAR 区别? | CHAR 定长,空间浪费但查询快;VARCHAR 变长,节省空间但需额外长度字节。 |
| Q2:VARCHAR 的最大长度? | 单列最大 65535 字节(与表行格式相关)。 |
| Q3:TEXT 类型存储在哪里? | 超出阈值后存储在溢出页(Off-page)。 |
| Q4:TEXT 能建索引吗? | 只能建立前缀索引。 |
| Q5:为什么 TEXT 不支持默认值? | 存储机制限制,无法在页外结构预定义默认内容。 |
| Q6:什么时候选用 CHAR? | 字段长度固定、频繁查询场景(如手机号)。 |
| Q7:VARCHAR 比 CHAR 更好吗? | 不是。它更节省空间,但需要权衡 CPU 成本和频繁更新带来的页分裂风险。 |
九、总结
MySQL 字符串类型的选择,看似简单,实则影响巨大。
一句话记住:
- CHAR:定长字段、追求速度;
- VARCHAR:变长字段、追求空间;
- TEXT:大字段、追求容量。
理解底层行格式(Compact/Dynamic)和溢出页机制,
你才能在项目中真正写出既节省空间又性能稳定的表结构。
下一篇(第 5 篇),我将写——
《B+树索引详解:从数据页到叶子节点的索引结构图》,
带你从物理页出发,直观理解 B+Tree 在 MySQL 中的索引组织方式。
