在 MySQL 表设计中,字符串字段常用 VARCHAR 和 TEXT 类型,但它们在 存储方式、性能、使用限制 等方面存在明显区别。
一、VARCHAR 和 TEXT 基本介绍
1. VARCHAR
- 可变长度字符串,最大长度由定义决定。
- 最大长度:0 ~ 65535 字节(受行大小限制)。
- 存储时需要额外 1-2 个字节记录字符串长度。
- 适用场景:长度可预估的字符串,如用户名、标题。
2. TEXT
- 专门用于存储大文本数据。
- 不需要指定长度,但 MySQL 有四种 TEXT 类型:
类型 | 最大长度 |
---|
TINYTEXT | 255 字节 |
TEXT | 65,535 字节 |
MEDIUMTEXT | 16,777,215 字节 |
LONGTEXT | 4,294,967,295 字节 |
- TEXT 不支持默认值。
- 适用场景:文章正文、评论、描述等大文本。
二、VARCHAR 和 TEXT 的主要区别
对比项 | VARCHAR | TEXT |
---|
存储方式 | 存储在 行内(页内),长度小于页大小(16KB) | 存储在 独立溢出页,行内只保存指针(20字节) |
最大长度 | 受表行大小限制(理论 65535 字节) | TEXT 类型分为 TINYTEXT ~ LONGTEXT |
是否需要指定长度 | 需要(如 VARCHAR(255)) | 不需要(直接使用 TEXT) |
默认值支持 | 支持 | 不支持 |
是否可以创建索引 | 可以,且索引长度可以完整覆盖 | 可以,但必须指定前缀长度(如 INDEX(title(100)) ) |
占用存储 | 字符串实际长度 + 1 或 2 字节长度信息 | 只存储 20B 指针,数据在溢出页 |
性能 | 访问速度快(行内存储) | 较慢(需要额外读取溢出页) |
适合场景 | 用户名、邮箱、标题 | 评论、正文、描述 |
三、存储结构差异
VARCHAR
- 数据直接存储在 页(Page)中,行内存储。
- 页大小默认 16KB,如果 VARCHAR 太大(> 16KB),会使用页外存储(类似 TEXT)。
TEXT
- TEXT 类型采用 页外存储:
- 行内存储 20 字节指针,指向溢出页。
- 实际数据存储在 溢出页(Overflow Page)。
- 因此 TEXT 类型访问需要 额外一次 I/O,性能略差。
四、索引方面的区别
五、内存占用差异
- VARCHAR(N):需要额外 1-2 字节存储长度信息。
- N ≤ 255,用 1 字节。
- N > 255,用 2 字节。
- TEXT:只存储一个 20B 指针在行内,实际数据在页外。
六、应用场景对比
场景 | 推荐类型 |
---|
用户名、邮箱、标题 | VARCHAR(50~255) |
文章正文、长评论 | TEXT(或 MEDIUMTEXT) |
大量短文本,需频繁查询 | VARCHAR |
大字段,偶尔查询 | TEXT |
七、限制与注意事项
- TEXT 字段不能有默认值。
- TEXT 字段不能直接排序,需要指定前缀:
SELECT * FROM articles ORDER BY SUBSTRING(content, 1, 100);
- TEXT 字段不能设置 FULLTEXT 索引,除非引擎支持(InnoDB 5.6+)。
- VARCHAR 受行大小限制,单行最大 65535 字节(不包括 BLOB/TEXT 外存数据)。
八、面试高频问答
Q1:VARCHAR 和 TEXT 的存储方式区别?
- VARCHAR 存储在页内(行内)。
- TEXT 存储在溢出页,行内只保留指针。
Q2:TEXT 字段为什么不能有默认值?
- 因为 TEXT 存储结构特殊,MySQL 没有为其分配默认值空间。
Q3:TEXT 可以建索引吗?
Q4:TEXT 查询为什么比 VARCHAR 慢?
Q5:什么时候选择 TEXT?
- 当字段内容长度不确定且可能非常大,比如文章正文、长评论。
九、总结
维度 | VARCHAR | TEXT |
---|
存储方式 | 行内 | 页外 |
是否指定长度 | 必须 | 不需要 |
默认值支持 | 支持 | 不支持 |
索引支持 | 完整支持 | 必须指定前缀 |
性能 | 高 | 较低 |
适用场景 | 短字符串 | 长文本 |
实践:
- 如果字段长度可以预估(如用户名、邮箱、标题):用 VARCHAR。
- 如果字段内容超大且不确定:用 TEXT。