VARCHAR 真比 CHAR 好?其实很多人都答错了!

81 阅读6分钟



前几天,我又去面了一家公司。作为一个有点小资历的31岁程序员,面试这种事儿其实早就习惯了,但每次还是有种“打怪升级”的感觉。

刚坐下来,面试官微微一笑,递过来一道经典面试题:

“那我们来个热身吧,你能说说 CHAR 和 VARCHAR 的区别吗?”

当时我心里咯噔一下:这题,真的是“老生常谈”啊!但同时,我也知道,这是很多社招面试官特别喜欢用来“划水+试探”的问题。看似简单,答得深,能看出你的底子和经验;答得浅,就容易被贴上“只会写CRUD”的标签。

所以,我干脆就把自己这几年踩过的坑、见过的项目问题,全都搬了出来。面试官笑眯眯地听着,最后点点头:“不错,你是真吃过亏的人。”

于是今天,我就把这段经历写出来,和你们聊聊 CHAR 和 VARCHAR 的区别,顺便讲讲里面那些容易忽略的细节。希望对准备面试的你有点帮助。

故事开头:项目中的“神奇Bug”

大概三年前,我在一家电商公司,做会员中心那块。某天,我们遇到一个超级诡异的问题:

会员表里有个 phone 字段,本来存的都是手机号,结果有用户反馈说:我注册时手机号写错了,改了之后,居然还能登录老账号?!

我们查数据库一看,明明手机号已经更新了,可是某些查询居然还能命中原本的手机号!

团队里炸开了锅。有人说是不是缓存没更新?有人说是不是代码逻辑有bug?但我仔细盯着表结构一看,立马发现了端倪:

对,字段居然用的是 CHAR。

于是我马上试了个实验:存进去一个手机号 1381234567(注意,只有10位),结果查出来变成了 1381234567␣(最后多了一个空格)。原来,CHAR 是定长的,不管你写多少,它都要填满长度!

再一查代码逻辑,发现有些地方用 = 比较手机号时,没做 trim,于是各种“幽灵手机号”就出现了。最后我们改成 VARCHAR(11),问题才算彻底解决。

从那以后,我对 CHAR 和 VARCHAR 的区别,再也没敢掉以轻心。

面试中的“标准答案”

好,先把最直白的区别列一下,这是面试官一般想听到的点:

1、存储方式不同

  • CHAR:定长,长度固定。不足会补空格,超长会截断。
  • VARCHAR:变长,按实际长度存储,还会额外占用 1~2 个字节记录长度信息。

2、存储效率不同

  • CHAR:因为是定长,存储和读取效率高,适合存放长度固定的数据(比如身份证号、MD5值、国家代码)。
  • VARCHAR:存储空间更节省,但在更新时可能会引起数据页分裂,导致性能下降。

3、空间占用不同

  • CHAR(n) 永远占用 n 个字符空间。
  • VARCHAR(n) 最多占 n 个字符 + 1~2 个字节(用于存储长度)。

4、尾部空格的处理

  • CHAR 会自动补空格,查询时 MySQL 会自动忽略这些空格。
  • VARCHAR 则不会自动补空格,保存什么就是什么。

到这一步,其实就能拿到“及格分”了。但如果只答到这,还不够打动面试官。那怎么办?很简单——继续深入。

进阶回答:实际应用场景

这才是能让面试官眼前一亮的地方。

  1. 什么时候用 CHAR?
  • 固定长度的字段: 比如:身份证号(18位)、性别(M/F)、国家代码(CN/US/JP)
  • 高频查询的字段: 因为定长,查询速度比 VARCHAR 要快一点点,尤其在索引上更稳定。
  1. 什么时候用 VARCHAR?
  • 长度不确定的字段: 比如昵称、邮箱、地址、手机号。
  • 节省存储空间: 如果字段内容长短差别特别大,CHAR 会浪费大量空间,这时候就用 VARCHAR。
  1. “混搭”策略

在实际项目中,有些团队喜欢把所有字符串字段都统一成 VARCHAR,图省事。但更讲究的做法是:

  • 对确实固定长度的字段,用 CHAR。
  • 对变化较大的,用 VARCHAR。
  • 而且要结合 查询频率字段大小 来权衡。

举个例子:

  • 用户表里 gender → CHAR(1)。
  • 用户表里 nickname → VARCHAR(50)。
  • 用户表里 phone → VARCHAR(11)(因为有些国家手机号不一定11位)。

深入一点:存储引擎的差异

面试官如果继续追问:“那在 InnoDB 里,它们的存储方式有什么不同呢?”

这个时候,很多人就开始紧张了。

其实很简单:

1、InnoDB

  • CHAR:定长存储,空间固定。
  • VARCHAR:变长存储,数据存在页里,但太长会放到溢出页上。

2、MyISAM(虽然现在少见了,但面试官有时会考)

  • 对 CHAR 和 VARCHAR 的处理方式不同,VARCHAR 在 MyISAM 里不太会引起性能问题,但在 InnoDB 里就要小心页分裂。

换句话说,很多人说 VARCHAR 比 CHAR 慢,实际上那是早期 MyISAM 的印象,在 InnoDB 里差别并没那么大。

再来点“骚操作”

我还遇到过一个挺有意思的场景。

有一次我们做一个日志表,里面有个字段是 status,表示日志状态,本来就只有几种:success、fail、pending。

一开始有人定义成了 VARCHAR(20),后来 DBA 看了直摇头:

“这种字段,完全可以用 CHAR(1) 存个数字,比如 0、1、2,再在代码里映射,不仅省空间,索引效率也高。”

后来一算,日志表一共几十亿条记录,光是这个字段就能省下好几个 G 的空间。

所以说,字段类型设计,其实是很考验经验的事儿

答题模板总结

最后,我给你们一个“标准面试答案模板”,如果你在面试的时候被问到,就可以这样回答:

1、定义

  • CHAR:定长字符串,不足补空格,查询时会去掉尾部空格。
  • VARCHAR:变长字符串,按实际长度存储,多占 1~2 字节记录长度。

2、区别

  • 存储方式不同:CHAR 定长,VARCHAR 变长。
  • 空间占用不同:CHAR(n) 总是 n,VARCHAR(n) 取决于实际长度。
  • 查询效率不同:CHAR 稍快,VARCHAR 节省空间但可能有额外开销。

3、应用场景

  • 固定长度、高频查询 → 用 CHAR。
  • 变长、节省空间 → 用 VARCHAR。

4、扩展点

  • 在 InnoDB 里,VARCHAR 太长可能溢出到溢出页。
  • 在索引里,CHAR 的对比更高效。
  • 设计时要考虑存储空间和查询效率的权衡。

这样一套下来,不仅显得你基础扎实,还能表现出项目经验。

结尾

说到底,CHAR 和 VARCHAR 的区别,很多人只停留在“一个定长一个变长”上,但真正的考点,是你能不能结合实际场景去分析。

毕竟,面试官想要的不是教科书,而是能解决问题的人。

就像我当年踩过 CHAR 的大坑一样,有了血泪教训,再遇到这道题,答案自然就不一样了。

所以,下次当你被问到这道题的时候,不妨也讲一个你自己的故事——那才是最打动人的答案。

END

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!