VARCHAR(255)比VARCHAR(256)省1字节,因前者长度前缀仅需1字节(≤255),后者需2字节(>255),每行固定多占1字节,千万级表累计达MB级冗余。

为什么 VARCHAR(255) 比 VARCHAR(256) 多省 1 字节?
核心就一条:MySQL 用长度前缀(length prefix)记录实际字符串字节数,而这个前缀的字节数取决于你定义的 VARCHAR 最大长度是否 ≤ 255。
当定义为 VARCHAR(255) 时,长度前缀固定占 1 字节;一旦写成 VARCHAR(256),前缀立刻升为 2 字节——不管字段里存的是空字符串还是 1 个字母,每行都多占 1 字节。
这 1 字节差异在单行看微不足道,但在千万级用户表中:
– 每行多 1 字节 → 整表多出 ~10 MB 存储
– 更关键的是,ALTER TABLE ... MODIFY COLUMN 从 256 改回 255 会触发全表重建(InnoDB),锁表时间随数据量线性增长
VARCHAR(255) 在 utf8mb4 下真能建索引吗?
不能直接全字段建索引,但 VARCHAR(255) 是“刚好够用”的临界选择——不是因为它能索引全部内容,而是因为它的理论最大字节数(255 × 4 = 1020)虽超限,但开发者可主动控制索引前缀长度。
- InnoDB 默认单列索引上限是 767 字节(MySQL 5.7 及以前)
-
VARCHAR(255)在 utf8mb4 下,前 191 字符最多占 191 × 4 = 764 字节 →INDEX(email(191))安全通过 - 而
VARCHAR(256)同样取前 191 字符,长度前缀却要多占 1 字节,白白浪费索引空间冗余
注意:即使开启 innodb_large_prefix=ON,过长的索引前缀仍会拖慢写入、降低 buffer pool 命中率,这不是配置能绕开的本质问题。
实际开发中怎么选长度才不踩坑?
别被“255 是默认值”带偏。真正决定长度的,是业务真实数据分布 + 是否建索引 + 字符集。
- 查真实最大长度:
SELECT MAX(LENGTH(username)) FROM users;,再加 10%~20% 冗余 - 验证前缀区分度:
SELECT COUNT(DISTINCT LEFT(email, 60)) / COUNT(*) FROM users;,> 0.95 就够了 - 固定格式字段直接卡死:
phone VARCHAR(15)、country_code CHAR(2) - 描述类或 URL 类字段超过 500 字符,优先用
TEXT,避免行溢出和锁升级
最容易被忽略的不是“该不该用 255”,而是没人去跑 EXPLAIN FORMAT=TREE 看执行计划里有没有用到 MEMORY 临时表——一旦用了,VARCHAR(255) 在 utf8mb4 下每行按 1022 字节预分配,而 VARCHAR(50) 只要 202 字节,差出来的内存可能直接让 JOIN 查询 OOM。


















