2. Schema 设计原则:命名规范、字段类型选择、版本号管理、兼容性设计
好,咱们进入正题。Schema 设计这事儿,看着简单,但坑是真不少。我见过太多系统,上线半年后因为 Schema 设计不合理,改又不敢改,推又推不动,最后只能硬扛着。
说白了,Schema 就是数据的骨架。骨架歪了,后面长多少肉都别扭。今天我把几个核心原则掰开揉碎讲清楚,都是我用真金白银换来的经验。
2.1 命名规范:别让名字成为灾难
命名这事,我一开始也觉得无所谓。直到有一次,我在一个遗留系统里看到 user_name、username、userName 三个字段同时存在,分别代表三个不同的业务含义……嗯,那感觉,就像吃面发现三根面条是三种颜色。
create_time,B 系统叫 created_at,C 系统叫 gmt_create。为了对齐这三个字段,我写了整整两天的 ETL 脚本。
命名规范,我建议你记住三条铁律:
- 全小写 + 下划线分隔:
order_id而不是orderId或OrderID。为什么?因为不同数据库对大小写敏感程度不一样,下划线是最大公约数。 - 业务含义优先:
user_registration_date比reg_dt好一万倍。别为了省几个字符,让后人猜谜语。 - 禁止保留字:别用
order、group、select做字段名。我见过有人用order做表名,每次查询都要加反引号,看着就累。
| 场景 | 推荐命名 | 不推荐命名 |
|---|---|---|
| 用户ID | user_id |
uid、userId、UserID |
| 创建时间 | created_at |
create_time、ct、gmt_create |
| 订单状态 | order_status |
status、ord_st、flag |
| 是否删除 | is_deleted |
del、delete_flag、valid |
2.2 字段类型选择:选错了就是给自己挖坑
字段类型这事,我见过最离谱的——有人用 VARCHAR(255) 存时间戳。你想想看,存进去的是字符串,查出来还得 CAST 一下,性能能好吗?
我个人习惯,字段类型选择遵循三个原则:
- 用对类型,别用万能类型:时间就用
TIMESTAMP或DATETIME,数字就用INT或BIGINT,别什么都往VARCHAR里塞。 - 精度够用就行:存年龄用
TINYINT就够了,别用INT。存金额用DECIMAL(10,2),别用FLOAT——浮点数有精度问题,算账会差一分钱。 - 考虑未来扩展:状态字段别用
INT存 0 和 1,万一以后要加个「待审核」状态呢?用VARCHAR存枚举值,或者用TINYINT预留几位。
核心原则: 字段类型的选择,决定了你的数据能做什么、不能做什么。选对了,查询快、存储省、维护简单。选错了,后面全是补丁。
举个例子,存用户性别:
- 错误做法:
gender INT(0 男 1 女 2 未知),你永远记不住 0 代表什么。 - 推荐做法:
gender VARCHAR(10),存male、female、unknown,一目了然。 - 更优做法:用枚举类型
ENUM('male', 'female', 'unknown'),既清晰又节省空间。
2.3 版本号管理:给 Schema 上个身份证
版本号这事,我一开始也没当回事。直到有一次,生产环境出了 Bug,我排查了半天才发现——代码是新的,但数据库 Schema 还是旧的。字段对不上,数据全乱了。
从那以后,我强制要求每个 Schema 都必须带版本号。怎么管?我建议这样做:
- 用
schema_version表:单独建一张表,记录当前 Schema 的版本号、变更时间、变更描述。 - 版本号格式:用语义化版本
v1.2.3,主版本号(不兼容变更)、次版本号(向下兼容的新功能)、修订号(Bug 修复)。 - 变更脚本统一管理:每次 Schema 变更都写一个 SQL 脚本,按版本号命名,比如
V1.2.3__add_user_email.sql。
举个例子,版本号管理流程:
-- 创建版本管理表
CREATE TABLE schema_version (
version VARCHAR(20) NOT NULL,
description VARCHAR(255),
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 每次变更后插入一条记录
INSERT INTO schema_version (version, description)
VALUES ('v1.2.3', '新增用户邮箱字段');
2.4 兼容性设计:向前兼容是底线
兼容性设计,说白了就是——你改了 Schema,别让老数据、老代码崩了。我见过最惨的一次,有人把字段类型从 INT 改成 VARCHAR,结果所有历史数据都读不出来了。
兼容性设计,我总结了几条硬规则:
- 只加不减:新版本可以加字段,但别删字段。老代码可能还在用呢。
- 只放宽不收紧:字段长度可以从
VARCHAR(50)改成VARCHAR(100),但别反过来。类型可以从INT改成BIGINT,但别从BIGINT改成INT。 - 新字段要有默认值:加字段时,给个默认值。不然老数据读出来是 NULL,代码没处理 NULL 就崩了。
- 废弃字段先标记后删除:想删字段?先标记为
deprecated,等所有依赖都清理干净了,再动手删。
来看一个兼容性设计的例子:
-- 旧版本:用户表
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL
);
-- 新版本:加字段,但不影响老数据
ALTER TABLE users ADD COLUMN email VARCHAR(100) DEFAULT '' NOT NULL;
-- 注意:加了 DEFAULT '',老数据自动填充空字符串,不会出现 NULL
2.5 知识体系总览
说了这么多,咱们用一张图把 Schema 设计的核心逻辑串起来。你一看就明白了。
这张图把四个核心原则串起来了。你看,命名规范是基础,字段类型是骨架,版本号是身份证,兼容性是安。四个缺一不可。
好了,Schema 设计原则就讲到这里。记住一句话:好的 Schema 设计,是让后来者看着舒服、改着放心、用着顺手。别让你的 Schema 成为别人的噩梦。