本文目录导读:
这是一个非常专业且重要的问题,字段类型选型是数据库设计的根基,选错了轻则浪费存储空间,重则拖垮性能。
简单归纳核心原则:在满足业务需求的前提下,选择占用空间最小、运算速度最快的类型。
下面从数据库通用和MySQL两个层面来详细讲解优化选型策略。
核心优化原则
- 最小化原则:能用
TINYINT绝不用INT,能存 2 位数,就别用VARCHAR(255),这直接减少磁盘 I/O、内存占用和索引树高度。 - 简单至上:能用整数型,绝不用字符型存数字,能用
DATE,绝不用VARCHAR存日期。 - 避免NULL:尽量将字段设置为
NOT NULL,并给出默认值,NULL 值会使索引更复杂,占用额外空间,且更难以优化。 - 匹配应用逻辑:类型不仅要考虑存储,还要考虑应用代码如何读取和比较。
常见字段类型优化选型指南
| 业务场景/数据类型 | 推荐类型 | 避免使用的类型 | 选型理由 |
|---|---|---|---|
| 布尔值/状态/开关 | TINYINT(1) 或 BIT |
CHAR(1) / VARCHAR(5) |
数值比较比字符串快几个数量级,存储只占1字节。 |
| 整数ID/主键 | BIGINT / INT / BIGINT UNSIGNED |
VARCHAR(36) (UUID) |
自增整数是MySQL InnoDB聚簇索引的天然最优选择,UUID强烈建议转为BINARY(16)有序存储。 |
| 小范围内的枚举值 | TINYINT / SMALLINT |
ENUM / VARCHAR |
整数枚举灵活性强,修改方便,无需执行 ALTER TABLE。 |
| 精确金钱/货币 | DECIMAL(10,2) |
FLOAT / DOUBLE |
浮点数有精度误差,会导致算账对不上。 |
| URL/邮箱/APP版本 | VARCHAR(255) |
TEXT |
绝大多数情况长度可控。VARCHAR 可以建索引,TEXT 索引效率低。 |
| 固定长度的代码(如身份证号) | CHAR(18) |
VARCHAR(18) |
长度固定,CHAR 检索速度比 VARCHAR 快,无额外开销。 |
| 用户姓名/短文本 | VARCHAR(50) ~ VARCHAR(100) |
VARCHAR(255) |
避免“一个字段管所有”,实际90%的人名都在10字以内。 |
| 长文本/富文本/JSON | TEXT / MEDIUMTEXT / JSON |
VARCHAR(8000) |
长文本存在溢出页,不影响主表行宽。 |
| IP地址 | INT UNSIGNED (IPv4) / VARBINARY(16) (IPv6) |
VARCHAR(15) |
整数存储4字节,字符串15字节,且支持快速范围查询。 |
| 日期/时间 | DATE / DATETIME / TIMESTAMP |
VARCHAR(10) 存字符串 |
原生日期类型支持时区、范围查询、日期函数,且存储效率极高。 |
MySQL 中的关键陷阱与优化细节
VARCHAR 长度误区
- 错误做法:
VARCHAR(500)“反正有备无患”。 - 正确做法:
VARCHAR(50)或VARCHAR(100)。 - 原因:MySQL 在排序时(如
ORDER BY时),会在内存中创建一个固定大小的临时表,长度就是字段定义的宽度。VARCHAR(500)比VARCHAR(50)多占10倍内存,极易触发磁盘临时表,导致性能灾难。
TEXT 和 BLOB 的隐藏成本
- 问题:
TEXT类型无法直接创建完整索引(除非前缀索引)。SELECT *时,读取TEXT列会导致行溢出,产生二次磁盘读。 - 优化方案:
- 尽量拆到单独的子表中。
- 或只存储其
MD5哈希值或摘要。 - 若必须存,只
SELECT你真正需要的列,永远不要SELECT *。
CHAR vs VARCHAR
CHAR:定长,速度极快,适合存储长度变化极小或固定的数据(如手机号、固定位数验证码、账户状态码)。VARCHAR:变长,节省空间,适合长度有明显差异的字符串(如用户昵称、地址),额外需要 1-2 字节存储长度信息。
TIMESTAMP vs DATETIME
TIMESTAMP:4字节,范围 1970-2038,自动时区转换,适合记录行最后修改时间(经常直接设DEFAULT CURRENT_TIMESTAMP)。DATETIME:5字节(新版MySQL 8.0+ 为 5字节,带精度时为 8 字节),范围 1000-9999,无时区影响,适合业务时间(如下单时间、生日)。
整数类型符号与无符号
- 推荐使用
UNSIGNED(无符号)。 INT UNSIGNED范围是 0~42亿,而INT范围是 -21亿~21亿,大多数业务主键和数量字段都非负,使用UNSIGNED相当于将上限翻了一番。
实战决策清单
当你设计一张表时,请按此顺序思考:
- 这个字段是数字还是字符串?
- 数字:
TINYINT->SMALLINT->MEDIUMINT->INT->BIGINT->DECIMAL。 - 字符串:
CHAR->VARCHAR->TEXT。
- 数字:
- 这个字段长度有上限吗?上限是多少?
- 固定长度:
CHAR。 - 长度小且差异大:
VARCHAR。 - 长度很大(> 65535 字符):
TEXT。
- 固定长度:
- 这个字段需要参与查询/排序吗?
- 需要:优先选择小空间、高运算效率的类型(整数优先于字符串)。
TEXT只能做前缀索引,效率低。 - 不需要:可以用
TEXT或JSON,但要警惕SELECT *拖慢性能。
- 需要:优先选择小空间、高运算效率的类型(整数优先于字符串)。
- 这个字段允许为空吗?
- 绝大多数情况下:
NOT NULL DEFAULT ...。
- 绝大多数情况下:
- 这个字段对精度有要求吗?
- 金钱:
DECIMAL。 - 一般计算:
FLOAT或DOUBLE(注意误差)。
- 金钱:
总结一句口诀
数字用定长、布尔用字节、日期用原生、长度刚刚好、拒绝用文本存一切、能用 NOT NULL 别留空。
按照这个思路进行字段选型,你的数据库设计会兼具高性能与低存储成本。
标签: 类型选型