CHAR 和 VARCHAR 有什么区别?
本文讲解了数据库字符串类型 CHAR 和 VARCHAR 的区别。CHAR 为定长,速度快但浪费空间;VARCHAR 为变长,节省空间,适用性更广。
这是一个非常经典和重要的数据库问题。CHAR 和 VARCHAR 都是用来存储字符串的数据类型,但它们在存储方式、性能和空间使用上有本质的区别。
简单来说,可以用一个生动的比喻来理解:
CHAR就像一个“预定车位”:你申请了一个能停10米长卡车的车位(CHAR(10))。无论你今天开来的是一辆5米的小轿车,还是10米的大卡车,这个车位都会占用10米的空间。小轿车停进去后,剩下的空间就空着(用空格填充)。VARCHAR就像一个“弹性车位”:你告诉管理员你最多需要一个10米的车位(VARCHAR(10))。当你开来一辆5米的小轿车时,管理员就只给你分配5米的空间(外加一点点记录长度的管理空间)。当你开来8米的车时,就给你8米的空间。它非常节省空间。
下面我们来详细地看它们的区别。
CHAR (定长字符串)
CHAR (Character) 是固定长度的字符串类型。
- 工作方式:当你定义一个字段为
CHAR(N)时,数据库会为这个字段始终分配 N 个字符的存储空间。 - 空间填充:如果你存入的字符串长度小于 N,数据库会自动在末尾填充空格来补足到 N 个字符的长度。
- 优点:
- 处理速度快:因为长度是固定的,数据库可以很容易地计算出每条记录的位置,所以在更新和查找时效率更高,尤其是在处理的都是定长数据时。
- 不易产生碎片:由于每条记录的这个字段长度都一样,更新操作不容易导致数据页(Data Page)的碎片化。
- 缺点:
- 浪费存储空间:如果存储的数据长度差异很大,会浪费大量的存储空间。例如,在
CHAR(20)的字段中存入 "你好" (2个字符),仍然会占用20个字符的空间。
- 浪费存储空间:如果存储的数据长度差异很大,会浪费大量的存储空间。例如,在
VARCHAR (变长字符串)
VARCHAR (Variable Character) 是可变长度的字符串类型。
- 工作方式:当你定义一个字段为
VARCHAR(N)时,N 代表的是最大允许长度。实际占用的空间是字符串的实际长度 + 1到2个字节的额外开销(这1-2个字节用来记录字符串的实际长度)。 - 空间利用:它只使用必要的空间。在
VARCHAR(20)的字段中存入 "你好",它实际占用的空间就是 "你好" 的长度 + 长度记录字节。 - 优点:
- 节省存储空间:当数据长度不确定时,能极大地节省磁盘空间。
- 灵活性高:适用于绝大多数的字符串存储场景。
- 缺点:
- 性能可能稍逊:在更新时,如果新字符串比旧字符串长,可能导致数据库需要移动整行数据到新的位置,从而产生“行迁移”(Row Migration)和数据页碎片,影响性能。
- 需要额外开销:需要额外的1或2个字节来存储长度信息。
对比总结表
| 特性 | CHAR | VARCHAR |
|---|---|---|
| 长度类型 | 固定长度 | 可变长度 |
| 定义 | CHAR(N):N 是固定的字符数 |
VARCHAR(N):N 是最大的字符数 |
| 空间分配 | 总是分配 N 个字符的空间 | 根据实际数据长度分配空间 |
| 空间填充 | 如果数据 < N,用空格填充到 N | 不填充,存储实际数据 |
| 存储开销 | 无额外开销 | 1-2字节的长度记录开销 |
| 存储效率 | 当数据长度几乎都相同时,效率高 | 当数据长度差异很大时,非常节省空间 |
| 性能 | 读取和更新速度快,不易产生碎片 | 更新可能导致碎片,性能略有损耗 |
| 最大长度 | 通常较短(如 MySQL 中为 255) | 通常较长(如 MySQL 中为 65535) |
如何选择?(选择指南)
什么时候使用 CHAR?
当你可以确定存储的数据长度是固定的时候,使用 CHAR 是最佳选择。
- MD5 或 SHA1 哈希值:如 MD5 总是32位,
CHAR(32)是完美选择。 - 性别:如果用 'M'/'F'/'U' 表示,
CHAR(1)很合适。 - 国家/地区代码:如中国的 'CN',美国的 'US',
CHAR(2)很合适。 - UUID:固定长度为36个字符,
CHAR(36)很合适。 - 固定长度的电话号码或邮政编码:例如,某个地区的邮编都是6位数,
CHAR(6)就很好。
什么时候使用 VARCHAR?
在绝大多数情况下,当数据长度不确定或变化较大时,VARCHAR 是更通用、更合适的选择。
- 用户名、密码(加密后)
- 文章标题、内容摘要
- 电子邮件地址、网址
- 地址信息
总结
CHAR追求性能,适用于定长数据,以空间换时间。VARCHAR追求灵活性和空间效率,适用于变长数据,是绝大多数场景下的首选。
在现代数据库应用中,由于磁盘空间成本的下降和数据库引擎的优化,VARCHAR 的性能损耗已经非常小,因此它成为了事实上的标准选择,除非你明确知道数据是定长的并且对性能有极致要求。