面试题
20 亿手机号存储,选 int 还是 string?varchar 还是 char?为什么?
思路
- 20 亿数据,用 Int 存储存在哪些问题?
- 面试官的隐藏考察点
- 日常开发避坑点
用 Int 或者 BigInt 有哪些问题
我们都知道手机号,是 11 位的数字,比如 13728199213 .
在 Java 中,int 是 32 位,最大值为 2^31 - 1 = 2,147,483,647。约等于 2×10⁹。显然,如果用 int,根本存不下 11 位的手机号码。
要想存得下,得用 64 位的 Long 类型,也就是对应数据库的 bigInt。
例如手机号 01324567890,用 Long 存会变成 1324567890,直接破坏数据完整性。 并且,有时候,有些手机号可能包含国家代码如 (+86),或者有些时候,是有连字符的,比如 137-2819-9213 . 这些原因都导致不能用整型类型存储。
比如,你要查找,手机号是 137 开头的手机号号码,如果用 BigInt (Long 类型)需先转字符串再模糊匹配,效率暴跌。
用 string 的好处
- 保真:数字、符号、前导零全能存,原样保留。
- 灵活:支持模糊查询、国际号码,扩展无忧。
- 省心:无需担心溢出或格式转换问题。
为什么用 VARCHAR(20) 而不是 VARCHAR(11)?
因为我们都知道,手机号是 11 位的,为什么不直接用 VARCHAR(11) 呢?
如果你日常开发中,就有思考数据容错性习惯的话,就会想到:
- 如果遇到国际号码:+8613822223333(14 位)
- 带国家码的号码:008613822223333(15 位)
- 分机号:13822223333 #123 (超 11 位)
这些场景,都会导致 VARCHAR(11) 报错崩盘。
其次就是业务扩展性思考:VARCHAR(11)只能存纯 11 位数字,假设未来业务需要:
- 支持座机号(如 010-62223333,含横杠)
- 支持虚拟号(如 17012341234-5678)
- 支持其他登录方式(如邮箱+手机号混合存储)
因此,字段长度和类型需提前为业务变化留余地,避免频繁改表。这就是日常开发中的,业务扩展性思维思考。
还有数据容错性思考,
- 输入不可控性:用户可能输入带空格/符号的号码(如 138 2222 3333),直接存原始值更方便清洗。
- 设计妥协:若强制用 VARCHAR(11),需在代码层严格过滤非数字字符,增加复杂度。
还有思考问题全面性,比如存储成本思考。
- VARCHAR(11):最大占 11 字节(utf 8 mb 4 下 1 字符占 4 字节,但数字和+号只占 1 字节)
- VARCHAR(20):最大占 20 字节
- 20 亿数据相差仅约 18 GB(和用 BIGINT 的 16 GB 对比,总成本仍可接受)。




