TechBlog
首页分类标签搜索关于

© 2025 TechBlog. All rights reserved.

mysql中-char-和-varchar-的区别

11/22/2025
未分类#数据库#Mysql

mysql中 char 和 varchar 的区别

[ 新星杯·14天创作挑战营·第17期 10w+人浏览 421人参与

](https://activity.csdn.net/writing?id=11028)

这是一个在 MySQL 面试和日常开发中非常经典的问题。CHAR 和 VARCHAR 是两种最常用的字符串数据类型,它们的核心区别在于存储和检索的方式。

下面我将从多个维度详细解释它们的区别,并给出选择建议。

核心区别总结

特性CHARVARCHAR
长度处理固定长度可变长度
存储方式分配定义的全部空间,不足部分用空格填充只存储实际字符数(+1或+2字节存储长度信息)
存储空间固定,为声明的长度可变,为实际字符串长度 + 长度前缀
尾部空格检索时会自动删除检索时会保留
读取速度较快(固定长度,无需计算)稍慢(需要根据长度信息读取)
适用场景长度固定或近乎固定的数据(如MD5、UUID、状态码)长度变化较大的数据(如姓名、地址、描述)

详细解释

1. 存储方式与空间占用
  • CHAR(n):

    • 你声明一个 CHAR(10) 的列,无论你存入 "hi"(2字符)还是 "hello"(5字符),MySQL 都会在磁盘上分配并占用 10 个字符的空间。
    • 如果存入的字符串长度不足,MySQL 会在其右侧用空格填充到指定长度。
    • 例如,存储 "A" 到 CHAR(4) 列,实际存储的是 "A   "。
  • VARCHAR(n):

    • 你声明一个 VARCHAR(10) 的列,存入 "hi" 大约占用 3 个字节(2个字符 + 1字节的长度前缀),存入 "hello" 大约占用 6 个字节(5个字符 + 1字节的长度前缀)。

    • VARCHAR 需要使用额外的 1 或 2 个字节来存储“字符串的长度”这个信息。

      • 如果声明的最大长度 n <= 255,则使用 1 个字节 作为长度前缀。
      • 如果声明的最大长度 n > 255,则使用 2 个字节 作为长度前缀。
    • 它只存储实际的字符串内容,不会用空格填充。

2. 尾部空格的处理(关键行为差异)

这是另一个非常重要的区别,尤其是在进行字符串比较时。

  • CHAR:在检索(SELECT)时会自动移除存储时填充的尾部空格。

    
    -- 假设有一个 CHAR(5) 的列
    INSERT INTO table (char_column) VALUES ('abc '); -- 存储为 'abc  '
    SELECT char_column, LENGTH(char_column) FROM table; 
    -- 检索结果:'abc',长度为 3(尾部空格被移除)
    
* **`VARCHAR`**:在**检索时会保留**尾部空格。

  ```

  -- 假设有一个 VARCHAR(5) 的列
  INSERT INTO table (varchar_column) VALUES ('abc  '); -- 存储 'abc  ' 及其长度信息
  SELECT varchar_column, LENGTH(varchar_column) FROM table;
  -- 检索结果:'abc  ',长度为 5(尾部空格被保留)
  ```

注意:由于 CHAR 的这种行为,当使用 = 比较时:

'abc '(CHAR)和 'abc'(CHAR)是相等的;

'abc '(CHAR)和 'abc'(VARCHAR)是相等的;

'abc '(VARCHAR)和 'abc'(VARCHAR)是不相等的。

3. 性能考量
  • CHAR:

    • 优点:由于长度固定,在磁盘上的记录也是定长的,所以读写速度通常更快。MySQL 可以很容易地计算出第 N 条记录的位置,尤其是在 MyISAM 这种存储引擎中,对于全表扫描或频繁更新的场景有优势。
    • 缺点:可能会浪费存储空间,尤其是当存储的数据长度远小于定义长度时。
  • VARCHAR:

    • 优点:节省存储空间。
    • 缺点:由于记录长度可变,更新数据可能会导致行的大小发生变化,从而可能引发页分裂(对于 InnoDB),影响一点性能。此外,读取时需要先读取长度信息,再读取具体数据,过程稍复杂。

如何选择?

请根据你的业务场景来决定:

  • 使用 CHAR 的情况:

    • 存储的字符串长度非常固定或变化极小。

    • 经典例子:

      • MD5/SHA1 哈希值(长度固定,如 MD5 总是 32字符)
      • UUID(虽然可以用 CHAR(36),但现在更推荐存储为二进制或使用 UUID_SHORT())
      • 国家代码(如 CHAR(2) 用于 'US', 'CN')
      • 定长的状态码或标志位(如 CHAR(1) 用于 'Y'/‘N’)
  • 避免使用CHAR的情况:

    • 需要精确保留字符串的原始格式(包括尾部空格)
  • 使用 VARCHAR 的情况:

    • 存储的字符串长度变化很大。

一个简单的例子


CREATE TABLE test_string (
    id INT PRIMARY KEY,
    fixed_char CHAR(5),
    variable_varchar VARCHAR(5)
);

INSERT INTO test_string (id, fixed_char, variable_varchar) VALUES
(1, 'A', 'A'),       -- CHAR存储 'A    ', VARCHAR存储 'A'
(2, 'ABCDE', 'ABCDE'); -- 两者都存满

-- 查询并显示长度
SELECT 
    fixed_char, 
    LENGTH(fixed_char) as char_length,
    variable_varchar, 
    LENGTH(variable_varchar) as varchar_length
FROM test_string;

结果可能如下:

fixed_charchar_lengthvariable_varcharvarchar_length
A1A1
ABCDE5ABCDE5

总结

  • 追求空间效率,数据长度多变 -> 选择 VARCHAR。这是绝大多数场景下的选择。
  • 追求极致性能,数据长度固定 -> 选择 CHAR。
  • 深刻理解 CHAR 会剔除检索结果的尾部空格 这一点,可以避免很多意想不到的查询 Bug。

在现代 MySQL 版本和 InnoDB 存储引擎下,对于大多数通用场景,VARCHAR 因其灵活性而更受欢迎。除非你非常确定某个字段的长度是绝对固定的,否则从 VARCHAR 开始通常是一个安全的选择。