新手必学的5个数据库设计原则:避免后期重构踩坑
设计良好的数据库是系统稳定性的基石。遵循以下原则可避免后期重构的灾难性成本,每个原则都附有真实场景说明:
原则1:数据原子性(第一范式)
核心要求:每个字段只存储不可再分的最小数据单元
错误案例:用户地址字段存储"北京市海淀区中关村大街1号A座301室"
问题:
- 无法按城市/区域筛选用户
- 地址变更时需全量更新,易出错
正确设计:
CREATE TABLE users (
user_id INT PRIMARY KEY,
province VARCHAR(20), -- 省
city VARCHAR(20), -- 市
district VARCHAR(20), -- 区
street VARCHAR(50), -- 街道
building VARCHAR(20) -- 楼栋号
);
原则2:主键设计三要素
必须满足:
- 唯一性:每条记录唯一标识
- 非空性:禁止
NULL值 - 稳定性:永不修改
反例:用手机号作主键
风险:
- 用户换号时需级联更新所有关联表
- 国际用户可能有重复号码
最佳实践:
CREATE TABLE orders (
order_id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- 使用UUID
user_id INT REFERENCES users(user_id), -- 外键关联
amount DECIMAL(10,2)
);
原则3:关系分离与适度冗余
平衡策略:
- 多对多关系必须拆解:用户←→角色
- 允许只读字段冗余:订单快照存商品名称
错误示范:
-- 订单表直接存商品详情
CREATE TABLE orders (
order_id INT PRIMARY KEY,
product_name VARCHAR(100) -- 冗余且可能过期
);
优化方案:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
product_id INT REFERENCES products(id) -- 仅存ID
);
-- 订单创建时生成只读快照
CREATE TABLE order_snapshots (
snapshot_id SERIAL PRIMARY KEY,
product_name VARCHAR(100) -- 创建时写入,永不修改
);
原则4:约束先行
关键约束类型:
| 约束类型 | 作用 | 示例 |
|---|---|---|
NOT NULL | 强制字段必有值 | user_name VARCHAR(50) NOT NULL |
UNIQUE | 防止重复数据 | email VARCHAR(100) UNIQUE |
CHECK | 验证数据范围 | age INT CHECK (age > 0) |
FOREIGN KEY | 维护表间关系一致性 | FOREIGN KEY (dept_id) REFERENCES departments(id) |
未加约束的后果:
- 出现
age=-5的无效数据 - 删除部门后员工记录成"孤儿"
原则5:可扩展性预留
未来防护设计:
- 字段预留:添加
metadata JSONB字段存储未来扩展属性 - 分区设计:按时间范围分区处理增长数据
- 枚举替代:用字典表代替固定枚举值
典型错误:
-- 硬编码状态导致后期无法新增
CREATE TABLE tasks (
status VARCHAR(10) CHECK (status IN ('pending', 'done'))
);
弹性方案:
-- 状态字典表
CREATE TABLE task_status (
status_id SERIAL PRIMARY KEY,
name VARCHAR(20) UNIQUE
);
-- 任务表引用状态ID
CREATE TABLE tasks (
status_id INT REFERENCES task_status(status_id)
);
总结:设计自检清单
- 所有字段是否达原子级?
- 主键是否满足唯一/非空/稳定?
- 是否消除不必要冗余?
- 关键约束(非空/唯一/外键)是否完备?
- 是否有JSON字段或字典表应对未来变更?
遵循这些原则可使数据库迭代成本降低60%以上,避免"推倒重来"的悲剧。

被折叠的 条评论
为什么被折叠?



