作为开发者,我们几乎每天都在和数据库打交道。在设计表结构时,一个经典的问题总是绕不开:“这个字段我应该用 VARCHAR(255) 还是 TEXT?” 很多人凭感觉选择了 VARCHAR,因为它似乎“更快”,或者因为大家都这么用。但你真的了解它们背后的巨大差异吗?
特别是当谈到长度限制时,VARCHAR、TEXT 和 BLOB 都和数字 65,535 有关,这更加剧了混淆。
今天,我们就来彻底终结这个困惑,深入探讨它们的本质区别,并为你提供一份清晰的选型指南和MySQL数据类型速查表。
一、VARCHAR 的长度之谜:到底能存多少字符?
这可能是关于 VARCHAR 最令人困惑的问题。VARCHAR(L) 中的 L 到底代表什么?L 最大能设为多少?
答案比你想象的要复杂,它取决于两个关键因素:字节限制和字符集。
1. 理论上限:65,535 字节
MySQL 规定,一个 VARCHAR 列的最大长度是 65,535 字节 (Bytes)。注意,是字节,不是字符!
2. 字符集的影响
一个字符占用多少字节,完全由你选择的字符集(Character Set)决定:
latin1: 每个字符占用 1 个字节。utf8(实为utf8mb3): 每个字符占用 1-3 个字节。utf8mb4(强烈推荐): 每个字符占用 1-4 个字节,可以存储 Emoji 表情。
因此,一个 VARCHAR 列能存储的最大字符数是 65,535 除以该字符集单个字符可能占用的最大字节数。
| 字符集 | 单字符最大字节数 | VARCHAR列理论最大字符数 |
|---|---|---|
latin1 |
1 | VARCHAR(65535) |
utf8 |
3 | VARCHAR(21845) |
utf8mb4 |
4 | VARCHAR(16383) |
结论:在最常用的
utf8mb4字符集下,VARCHAR列最多可以定义为VARCHAR(16383)。
3. 行大小限制 (Row Size Limit)
还有一个更重要的限制:MySQL 中任何一行的总大小不能超过 65,535 字节。
这意味着,即使 VARCHAR 理论上可以很大,但一张表中所有列(包括 VARCHAR、INT、DATETIME 等)的数据加起来的总长度不能超过这个限制。如果你试图创建一个列总长度超过限制的表,MySQL 会直接报错。
二、终极对决:VARCHAR vs. TEXT vs. BLOB
既然它们都和 65,535 有关,那它们的区别到底在哪?核心区别在于存储方式和性能影响。
简单来说:
VARCHAR的数据主要存在行内 (in-row),而TEXT和BLOB的数据主要存在行外 (off-row)。
| 特性 | VARCHAR(L) |
TEXT |
BLOB |
|---|---|---|---|
| 核心概念 | 可变长度字符串 | 可变长度长文本 | 可变长度二进制大对象 |
| 存储方式 | 行内存储。数据直接存在数据行里,查询时一次性读出。 | 行外存储。行内只存一个指向外部存储区域的指针,需要时再二次查找。 | 与 TEXT 相同,行外存储。 |
| 长度限制 | 受整行大小限制。所有列加起来不能超过 65,535 字节。 | 自身数据限制。TEXT 本身最大可存 65,535 字符,其大小不计入行大小限制(除了指针)。 |
BLOB 本身最大可存 65,535 字节。 |
| 长度定义 | 必须指定长度,如 VARCHAR(255)。 |
无需指定长度,直接用 TEXT。 |
无需指定长度。 |
| 索引能力 | 可创建完整索引。只要索引长度在限制内,可以对整个列建索引,查询效率高。 | 只能创建前缀索引,如 INDEX(content(100))。无法对全文进行高效索引。 |
与 TEXT 相同,只能创建前缀索引。 |
| 数据类型 | 字符数据。受字符集和校对规则影响(如不区分大小写)。 | 字符数据。同 VARCHAR。 |
二进制数据。原始字节流,没有字符集概念,比较时严格区分大小写。 |
DEFAULT 值 |
可以指定 DEFAULT 值。 |
新版MySQL可以,但通常不建议。 | 新版MySQL可以,但通常不建议。 |
| 内存使用 | 排序或创建临时表时,倾向于在内存中操作,效率高。 | 操作时,倾向于在磁盘上创建临时表,性能开销大。 | 与 TEXT 相同。 |
三、如何做出正确选择?一份实用的选型指南
| 场景 | 推荐类型 | 例子 | 理由 |
|---|---|---|---|
| 短的、长度可预知、需要索引 | VARCHAR |
用户名、邮箱、标题、订单号 | 性能好,可完整索引,查询快。 |
| 长的、不确定多长的文本内容 | TEXT / MEDIUMTEXT / LONGTEXT |
博客文章、商品描述、用户评论 | 不会撑爆行大小限制,适合存储大段文本。 |
| 非文本数据(文件、图片等) | BLOB / MEDIUMBLOB / LONGBLOB |
存储加密数据、序列化对象 | 专为二进制数据设计。 |
最佳实践: 除非你有特殊需求,否则不要在数据库中存储大文件(如图片、视频)。更好的做法是,将文件上传到对象存储服务(如 AWS S3、阿里云 OSS),然后在数据库的
VARCHAR字段中只存储文件的 URL 或路径。
四、附录:MySQL常用数据类型速查表
为了方便你随时查阅,这里整理了一份常用数据类型的速查表。
1. 数值类型
| 类型 | 存储空间 | 范围 (有符号) |
|---|---|---|
TINYINT |
1 字节 | -128 到 127 |
SMALLINT |
2 字节 | -32,768 到 32,767 |
INT |
4 字节 | -21亿 到 21亿 |
BIGINT |
8 字节 | 约 -9.2 x 10¹⁸ 到 9.2 x 10¹⁸ |
DECIMAL(M,D) |
M+2 字节 | 精确小数,用于货币。 |
FLOAT |
4 字节 | 单精度浮点数 |
DOUBLE |
8 字节 | 双精度浮点数 |
2. 字符串类型
| 类型 | 长度/存储 |
|---|---|
CHAR(L) |
固定长度,0-255字符 |
VARCHAR(L) |
可变长度,0-65,535字节 |
TINYTEXT |
最多 255 字符 |
TEXT |
最多 65,535 字符 |
MEDIUMTEXT |
最多 16M 字符 |
LONGTEXT |
最多 4G 字符 |
TINYBLOB |
最多 255 字节 |
BLOB |
最多 64KB |
MEDIUMBLOB |
最多 16MB |
LONGBLOB |
最多 4GB |
3. 日期和时间类型
| 类型 | 存储空间 | 格式 | 范围 |
|---|---|---|---|
DATE |
3 字节 | 'YYYY-MM-DD' | '1000-01-01' 到 '9999-12-31' |
TIME |
3 字节 | 'HH:MM:SS' | '-838:59:59' 到 '838:59:59' |
DATETIME |
8 字节 | 'YYYY-MM-DD HH:MM:SS' | '1000-01-01…' 到 '9999-12-31…' |
TIMESTAMP |
4 字节 | 'YYYY-MM-DD HH:MM:SS' | '1970-01-01…' 到 '2038-01-19…' (UTC) |
YEAR |
1 字节 | YYYY | 1901 到 2155 |
4. JSON 类型
| 类型 | 描述 |
|---|---|
JSON |
用于存储 JSON 文档,有专门的函数进行高效操作。 |
总结
选择正确的数据类型是数据库设计的基石。现在,你应该能清晰地理解:
VARCHAR是为短的、需要索引的字符串设计的,其数据在行内,受行大小限制。TEXT和BLOB是为大的数据块设计的,其数据在行外,不会影响行大小,但索引和内存操作性能较差。
下次设计数据库时,不要再凭感觉选择,而是根据你的数据特性和业务需求,做出最专业、最高效的决策!