MySQL 中 CHAR、VARCHAR 和 TEXT 有什么区别?
简化版
CHAR 是定长字符串,适合长度固定的数据;VARCHAR 是变长字符串,适合长度变化但有明确上限的字段;TEXT 用于较长文本,通常不适合作为频繁排序、过滤和索引的主字段。
详细版
CHAR(n) 会按固定长度存储,短内容可能补空格,适合国家码、状态码、MD5 这类长度稳定字段。VARCHAR(n) 按实际长度存储并额外记录长度,适合用户名、标题、邮箱等大多数业务字符串。
TEXT 面向长文本,长度上限更大,但默认值、索引长度、排序和临时表处理上往往有更多限制或成本。能用 VARCHAR 表达清楚上限时,不要随手把字段设成 TEXT。
面试回答还要注意字符集。VARCHAR(100) 表示最多 100 个字符,不等于 100 字节;使用 utf8mb4 时,一个字符最多可能占 4 字节。
完整版教学
一、先区分定长和变长
CHAR 是定长,VARCHAR 是变长。定长意味着字段声明多长,存储和比较时就围绕这个固定长度处理;变长则会根据实际内容长度存储。
CREATE TABLE demo (
code CHAR(6),
name VARCHAR(50)
);
如果 code='CN',CHAR(6) 仍然按固定长度语义处理;如果 name='Tom',VARCHAR(50) 主要保存实际内容和长度信息。
记忆钩子:长度固定用
CHAR,长度浮动用VARCHAR,大段正文才考虑TEXT。
二、CHAR 适合什么场景
CHAR 适合长度非常稳定的字段,比如性别编码、国家码、定长 hash、状态短码。
CREATE TABLE api_keys (
id BIGINT PRIMARY KEY,
md5 CHAR(32),
country_code CHAR(2)
);
如果所有值都是 32 位 MD5,使用 CHAR(32) 语义清楚,长度固定也方便比较。若字段长度差异很大,例如昵称从 1 到 50 个字符都有,CHAR(50) 就会浪费空间。
假设 100 万行昵称平均 6 个字符,使用 CHAR(50) 会为短昵称付出明显额外空间;VARCHAR(50) 更合适。
三、VARCHAR 是业务字段主力
VARCHAR 适合有明确最大长度、但实际长度变化的字段。
CREATE TABLE users (
id BIGINT PRIMARY KEY,
nickname VARCHAR(50),
email VARCHAR(255)
);
它会额外使用 1 或 2 个字节记录长度,具体取决于最大长度。这个额外成本通常比 CHAR 浪费大量填充空间更划算。
| 字段 | 推荐类型 | 原因 |
|---|---|---|
| 手机号 | VARCHAR(20) 或按规范设计 | 可能有区号、加号 |
| 邮箱 | VARCHAR(255) | 长度变化明显 |
| 状态码 | VARCHAR 或短 CHAR | 看编码是否固定 |
| 标题 | VARCHAR(200) | 有上限且常过滤展示 |
设计 VARCHAR 时要给出业务上限,不要盲目写很大。
四、TEXT 的代价在哪里
TEXT 适合文章正文、评论内容、描述字段这类长文本。它的问题不在于不能用,而是不能滥用。
CREATE TABLE articles (
id BIGINT PRIMARY KEY,
title VARCHAR(200),
content TEXT
);
长文本字段可能影响临时表、排序、网络传输和页存储。对 TEXT 建索引时通常需要指定前缀长度:
CREATE INDEX idx_content_prefix ON articles(content(100));
前缀索引只能利用前 100 个字符,区分度和查询语义都要谨慎评估。对于频繁过滤和排序的字段,应尽量使用有明确长度的 VARCHAR 或单独设计检索方案。
五、字符数和字节数不要混淆
VARCHAR(100) 中的 100 通常表示字符数上限,而实际存储会受字符集影响。
在 utf8mb4 下:
英文 A:通常 1 字节
常见中文:通常 3 字节
部分 emoji:可能 4 字节
所以 VARCHAR(100) 最多可能需要约 400 字节存储字符内容,再加长度字节等开销。
这对索引长度也有影响。复合索引中放多个长 VARCHAR 字段,可能让索引项变大,降低页容纳量和缓存效率。
六、字段类型会影响索引和排序
字符串字段越长,索引越大;索引越大,B+ 树节点能放的键越少,查询和缓存成本可能越高。
例如:
CREATE INDEX idx_title ON articles(title);
title VARCHAR(200) 通常合理;如果把标题设计为 TEXT 再建前缀索引,可能无法完整支持精确排序和唯一约束。
对需要频繁排序的字段:
SELECT id, title
FROM articles
ORDER BY title
LIMIT 20;
字段类型、长度、字符集和索引都会影响执行计划。类型设计不是表结构小事,它会一路影响查询性能。
七、常见误区与追问
- 误区:
VARCHAR永远比CHAR好。 长度完全固定的字段用CHAR可能更清晰。 - 误区:
TEXT更大,所以字段都用TEXT更省心。TEXT在默认值、索引、排序和临时表上成本更高。 - 误区:
VARCHAR(100)就是 100 字节。 它通常表示 100 个字符,字节数取决于字符集。 - 误区:字符串长度设计只影响存储空间。 它还影响索引大小、缓存命中和排序成本。
- 追问:手机号用数字还是字符串? 通常用字符串,因为可能有前导 0、国家码和加号,不参与数值计算。
- 追问:长文本要搜索怎么办? 不应只靠普通
LIKE '%xxx%',可评估全文索引或搜索引擎方案。
八、加强记忆
字符串类型题按“固定、变化、长文”来选:固定长度用 CHAR,业务字符串用 VARCHAR,文章正文类用 TEXT。再补上字符集和索引成本,答案就不只是背类型,而是能指导表设计。