mysql中varchar 与 char 的区别?
在 MySQL 中,VARCHAR
和 CHAR
都是用于存储字符串的数据类型,但它们在存储方式、空间占用、性能和使用场景上有显著区别:
核心区别总结表
特性 | CHAR | VARCHAR |
---|---|---|
存储方式 | 固定长度 | 可变长度 |
空间占用 | 始终占用定义的长度 | 仅占用实际数据长度 + 额外字节 |
存储示例 | CHAR(10) 存储 "abc" → 占用 10 字节 | VARCHAR(10) 存储 "abc" → 占用 4 字节 |
读写性能 | 读取更快(无长度计算) | 读取稍慢(需计算长度) |
适用场景 | 定长数据(如 MD5、国家代码) | 变长数据(如用户名、地址) |
最大长度 | 255 字符(受字符集影响) | 65,535 字节(受行大小限制) |
尾部空格处理 | 自动填充空格,检索时移除 | 保留原始空格 |
详细解析
1. 存储方式
CHAR(N)
固定长度,始终占用N
个字符的空间(不足部分用空格填充)。
示例:CHAR(10)
存储"abc"
→ 实际存储"abc "
(补充 7 个空格)。VARCHAR(N)
可变长度,仅存储实际内容 + 额外长度标识(1-2 字节)。
示例:VARCHAR(10)
存储"abc"
→ 存储"abc"
+ 长度标识3
(共 4 字节)。
2. 空间占用
CHAR
空间公式:
N × 字符集字节数
(如utf8mb4
中 1 字符=4 字节)。存储
"a"
在CHAR(10) utf8mb4
中占用 40 字节(无论实际内容多短)。VARCHAR
空间公式:
实际字符数 × 字符集字节数 + 长度标识(1-2 字节)
。存储
"a"
在VARCHAR(10) utf8mb4
中占用 5 字节(1字符×4 + 1字节长度标识)。
关键结论:短文本用 VARCHAR
更节省空间;完全定长数据用 CHAR
无浪费。
3. 性能对比
读取速度:
CHAR
>VARCHAR
(CHAR
长度固定,无需计算实际长度)。更新效率:
CHAR
>VARCHAR
(定长数据更新不会引发行迁移)。存储碎片:
VARCHAR
更易产生碎片(长度变化可能导致页分裂)。
4. 适用场景
优先用
CHAR
:数据长度完全固定(如 MD5 哈希值、UUID、国家代码
CHAR(2)
)。高频读写的列(利用定长性能优势)。
优先用
VARCHAR
:数据长度变化大(如用户名、地址、描述文本)。
存储空间有限或需优化大表存储。
5. 其他注意事项
最大长度限制:
CHAR
最大 255 字符(受字符集影响,如utf8mb4
下最大 255×4=1020 字节)。VARCHAR
最大 65,535 字节(需减去表中其他列占用的空间)。空格处理:
CHAR
:插入时自动填充空格,检索时移除尾部空格。VARCHAR
:保留原始空格(存储和检索一致)。索引效率:
对CHAR
和VARCHAR
建索引无显著差异,但定长数据可能略微提升索引扫描速度。
示例:
CREATE TABLE example ( fixed_code CHAR(5), -- 存储国家代码(如 'CN', 'US') dynamic_data VARCHAR(100) -- 存储用户留言 ); INSERT INTO example VALUES ('CN', 'Hello'), -- CHAR(5) 实际存储 'CN ' ('US', 'MySQL rocks!'); -- VARCHAR(100) 仅存 12 字符 + 1 字节长度标识
总结:
数据长度是否绝对固定?
是 → 用
CHAR
(如性别M
/F
、邮编、枚举代码)。否 → 用
VARCHAR
(如姓名、标题、描述)。是否极端追求性能?
是 → 定长数据用
CHAR
(如高频访问的用户状态字段)。否 →
VARCHAR
更通用。存储空间是否敏感?
是 →
VARCHAR
显著节省空间(尤其文本平均长度远小于定义时)。