INT固定占4字节,VARCHAR(10)存"123"用4字节、存"1234567890"用11字节;INT索引比VARCHAR快因整数直接比较,而VARCHAR需逐字节比且受字符集影响。

Int 和 VARCHAR 存储空间到底差多少
直接看底层:一个 INT 在 MySQL 中固定占 4 字节(有符号),无论存 1 还是 999999999;而 VARCHAR(10) 存 "123" 实际用 3 字节 + 1 字节长度头(VARCHAR 长度 ≤ 255 时头占 1 字节),共 4 字节;但存 "1234567890" 就要 10 + 1 = 11 字节。越长、越不规律的值,VARCHAR 越“胖”。
更关键的是,INT 支持整数索引的 B+ 树快速比较(CPU 直接比大小),而 VARCHAR 索引需逐字节比较、受字符集影响(比如 utf8mb4 下一个汉字占 4 字节,比较开销翻倍),查询性能差距在百万级数据后就明显了。
什么时候非用 VARCHAR 不可
不是所有数字都该用 INT。以下情况硬转 INT 反而埋雷:
- 带前导零的编号,如工号
"00123"→ 转INT后变成123,丢失信息 - 含字母或分隔符的编码,如订单号
"ORD-2024-0001"、身份证号(末位可能是 X) - 超 32 位的数字,如雪花 ID(64 位整数),
BIGINT虽能存,但 PHP/Java 等语言处理易溢出,常统一用VARCHAR(20)安全落地
此时选 VARCHAR 不是妥协,是保数据语义正确性的必须。
VARCHAR 长度设多少才不浪费又够用
VARCHAR 的括号里填的不是“建议长度”,而是“最大长度”,它直接影响行格式和内存临时表分配策略。设太大有隐性成本:
-
VARCHAR(255)和VARCHAR(100)在 InnoDB 行存储中可能占用相同空间(如果实际值都短),但排序/分组时 MySQL 会按 255 分配内存 buffer,拖慢ORDER BY或GROUP BY - 联合索引中,
VARCHAR字段长度超 767 字节(utf8mb4下约 191 字符),可能触发index column size too large错误
实操建议:按业务上限+10% 冗余设长,比如手机号固定 11 位,用 VARCHAR(13)(预留国家码和+号);别无脑写 VARCHAR(255)。
自增主键为什么强烈推荐 BIGINT 而非 INT
很多老项目用 INT UNSIGNED(上限 42.9 亿)做自增主键,上线三年一跑满,迁移成本极高。现在新表直接上 BIGINT 几乎零代价:
- 磁盘空间只多 4 字节/行(从 4B 到 8B),对绝大多数业务可忽略
- InnoDB 的主键即聚簇索引,
BIGINT比VARCHAR做主键仍快得多(无字符串比较、无字符集转换) - 避免某天凌晨收到
ERROR 1467 (HY000): Failed to read auto-increment value from storage engine
真正要注意的不是类型本身,而是下游系统是否兼容:比如某些 ORM 对 BIGINT 返回字符串而非整数,前端 JSON 序列化可能精度丢失(JavaScript Number 安全整数上限是 2^53-1),这时得配合 JSON.stringify 或后端转字符串输出。



















