varchar(50) 的50到底是什么?90%的人都答错了

大家好呀,我是小米,一个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岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
十八号当铺的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容