大家好呀,我是小米,一个31岁还在折腾技术和写文的小码农。前几天在陪朋友刷面试题的时候,遇到一个看似“送命题”的问题:
面试官淡淡一笑,问:“你能解释一下 varchar(50) 中 50 的涵义吗?”
别小看这道题,它背后藏着的坑,能直接把一个“纸上谈兵”的候选人和一个“真有经验”的开发者区分开来。
今天我就带大家走一遍完整的思路,不仅搞清楚 varchar(50) 的真正含义,还会顺带拆解一下 MySQL8.x 中字符串存储的那些细节。保证你看完之后,下次面试官再露出那种“你懂不懂”的表情时,你能用故事把他反杀!
故事的开头:小张的“50字困惑”
小张是我一个师弟,前几天去参加一家互联网公司的面试。面试官笑眯眯地抛出问题:
“数据库里建表的时候,我们经常写 varchar(50),那这个 50 到底是什么意思呢?”
小张心里一惊,心想:这还不简单嘛,varchar(50) 不就是能存放 50 个字符吗?于是他脱口而出:
“这个 50 表示最多能存 50 个字符!”
面试官微微一笑,摇了摇头,说:“不完全对,你再想想。”
小张当时就慌了:难道不是字符?难道是字节?还是说和编码有关?
回去之后,他赶紧来找我,问我到底怎么回答才算到位。于是我们俩就一起翻文档、做实验、分析源码,最终把这道题彻底啃透了。
第一层理解:varchar(50) ≠ 50字节
先来澄清一个 最常见的误区。
很多同学会说:varchar(50) 中的 50 表示最多能存放 50 个 字节。
其实这在 MySQL8.x 中是不准确的。原因就在于:
varchar(n) 中的 n 表示最大字符长度,而不是字节长度。所谓字符长度,指的是逻辑上的字符数,而字节数则取决于字符集。
比如:
如果表的字符集是 latin1,那么一个字符 = 1 字节,varchar(50) 确实最多 50 字节。如果表的字符集是 utf8mb4,那么一个字符最多 4 个字节,所以 varchar(50) 最多需要 200 字节 的存储空间。
所以,当面试官问起这个问题时,第一点就要明确:
varchar(50) 的 50 指的是字符数,而不是字节数。
第二层理解:存储限制还受页面约束
好,你可能会问:既然是字符,那是不是只要 50 个就行?
并不完全是。
MySQL 对一行的数据存储有上限:一个 InnoDB 页(默认 16KB)中,行数据不能超过 65535 字节。
这意味着,如果你定义了一个超大的 varchar(n),比如 varchar(65535),在 utf8mb4 下根本存不下,因为一个字符就可能要 4 字节,实际最大只能到大约 16383 个字符左右。
所以,varchar(50) 表示最多 50 个字符,但前提是行总长度别超过 MySQL 的存储上限。
这就是第二层坑。
第三层理解:长度和实际占用空间
很多人以为 varchar(50) 一定会占 50 个字符的空间,其实不然。
在 InnoDB 中,varchar 是变长存储:
真实存储空间 = 实际字符长度 × 字节数 + 1~2 字节的长度记录。只有你真的存了多少字符,才会占用对应的空间。
举个例子:
在 utf8mb4 下,存 “abc” → 占 3 × 1 + 1 = 4 字节。存 “小米” → 每个汉字占 3 字节,共 6 + 1 = 7 字节。
所以,varchar(50) 并不是“浪费空间的选择”,它只是一种限制,而不是强制分配。
这也是为什么在大多数情况下,推荐用 varchar 而不是 char,因为 char 是定长存储,会固定分配空间。
面试中的回答层次
我们把这个问题整理成一个面试答题的“梯度”,你可以根据面试官深挖的程度逐步展开。
第一层:最基本答法
varchar(50) 的 50 表示最多能存放 50 个字符,而不是字节。
第二层:进阶答法
实际能存多少字节取决于字符集,比如 utf8mb4 下最多可能占 200 字节。
同时一行数据大小受限,最多 65535 字节。
第三层:专业答法
varchar 是变长存储,真正占用的空间是实际字符长度 × 字节数,再加上 1~2 字节的长度记录。
因此 varchar(50) 并不是预留 50 的空间,而是限制最多 50 个字符。
第四层:拔高答法
为什么推荐 varchar 而不是 char?因为 varchar 节省空间,适合不定长的字符串存储;char 固定长度,适合存放身份证号、手机号这种长度固定的字段。
同时,设计数据库表时,不必盲目给 varchar 指定特别大的长度,否则在某些索引或排序场景下会带来额外的存储和性能负担。
现实中的“坑”:varchar(50) 不是万能
我们再回到小张的故事。
他后来总结了几个自己踩过的坑,我觉得特别有价值:
1、联合索引长度超限
在 utf8mb4 下,varchar(255) × 多列建索引时,可能报错:
Specified key was too long.
因为 InnoDB 对单个索引前缀长度有限制(767 字节,MySQL8.x 可调到 3072 字节)。
2、存储 emoji 表情失败
如果字段用的是 utf8 而不是 utf8mb4,遇到 emoji 直接报错,因为 utf8 只支持最多 3 字节,而 emoji 需要 4 字节。
3、过度设计 varchar
有些同事喜欢一律 varchar(255),看似省事,但在索引、排序时可能带来额外负担。
比如姓名这种字段,给个 varchar(50) 足够,没必要 varchar(255)。
所以,varchar(50) 中的 50 不仅仅是一个数字,它还关系到存储效率、索引设计以及未来扩展性。
结尾:小张的反杀
故事的最后,小张再次面试。面试官又问起了同样的问题。
这次,小张先稳稳地说:
“varchar(50) 的 50 表示最大能存放 50 个字符,不是字节。”
接着,他补充:
“不过实际占用空间和字符集有关,比如 utf8mb4 下可能要 200 字节。另外 varchar 是变长存储,它不会预留空间,只按实际内容存储,还会额外加 1~2 字节表示长度。一行数据也受限于最大 65535 字节。”
最后,他笑着补充了一句:
“所以选字段长度时,不能一律 varchar(255),要结合业务来设计,比如名字 varchar(50) 就足够。”
面试官听完,点点头,嘴角终于露出满意的笑容。
总结(给你复盘一遍答题要点)
varchar(50) 的 50 表示最大字符数,而不是字节数。实际字节数取决于字符集,比如 utf8mb4 下最多 200 字节。varchar 是变长存储,只占用实际长度 + 1~2 字节的长度信息。一行数据总大小受 65535 字节限制。设计表时要考虑存储效率和索引限制,不要盲目用 varchar(255)。
END
写到这里,我觉得这个问题最大的魅力就在于:它看似简单,却能让面试官瞬间判断你是真正理解底层,还是停留在表面。
所以呀,下一次如果你遇到这个问题,希望你能像小张一样,从容不迫,稳稳反杀!
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
暂无评论内容