如何给项目设计数据库
在独立开发一个具备基本功能的网站时,需求分析与数据库设计往往是最耗时的部分之一
第一次从零开始设计数据库,我查阅了大量资料,也研究了很多成熟项目的数据库结构。以下是我在这个过程中总结的一些经验
设计一个规范的数据库
先问自己三个问题:
- 要存什么?
- 怎么存才能称得上合理?
- 怎么存得快、查得快?
要存什么?
这个问题相对简单
我在开发前已经进行了详细的需求分析,并梳理出了系统所需的业务实体。基于这些实体,数据库中的表和字段基本可以确定
怎么存才能称得上合理?
也就是数据库结构怎么设计更规范、更清晰。
我翻阅了《数据库设计》相关资料,复习了这个经典准则:数据库三范式(3NF)。几乎所有成熟系统的数据库结构,都遵循这一设计方法
1NF:字段不可拆分
2NF:字段完全依赖主键
3NF:字段不传递依赖主键
实际开发中,为了性能可以适度反范式化,也就是有意识地违反三范式以提升查询效率
后面会详细将三范式
命名规范建议
- 使用英文小写 + 下划线(如
user_id) - 避免使用拼音或不常见缩写
- 表名通常用复数(如
users、orders)
到这里作为初学者已经结束了,接下来的内容是为了让项目的数据库更加完善
怎么存得快、查得快?
这里说两种常用的方式吧:
1. 添加必要的索引
- 主键索引:如自增
id - 唯一索引:如
user_account - 普通索引:用于查询筛选字段,如
status,created_time
索引虽能提高查询速度,但也会增加写入成本,需合理设计
2. 反范式化
- 为了提高性能,可以适当冗余部分数据,例如:
- 在评论表中直接存储用户昵称(避免频繁关联用户表)
- 拆分表结构:将日志、历史数据单独建表(如
log_xxx、history_xxx)
数据库三范式
第一范式(1NF):要求数据库表的每一列都是不可分割的原子数据项。
举例说明:
在上面的表中,“家庭信息”和“学校信息”列均不满足原子性的要求,故不满足第一范式,调整如下:
可见,调整后的每一列都是不可再分的,因此满足第一范式(1NF);
第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
举例说明:
在上图所示的情况中,同一个订单中可能包含不同的产品,因此主键必须是“订单号”和“产品号”联合组成,
但可以发现,产品数量、产品折扣、产品价格与“订单号”和“产品号”都相关,但是订单金额和订单时间仅与“订单号”相关,与“产品号”无关,
这样就不满足第二范式的要求,调整如下,需分成两个表:
第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
举例说明:
上表中,所有属性都完全依赖于学号,所以满足第二范式,但是“班主任性别”和“班主任年龄”直接依赖的是“班主任姓名”,
而不是主键“学号”,所以需做如下调整:
这样以来,就满足了第三范式的要求。
设计一个高可扩展性与可维护性的数据库
1. 预留扩展字段
- 使用 JSON 格式扩展字段(如
ext_json)存储一些不固定字段 - 对不常用数据做非结构化存储,提升灵活性
2. 逻辑删除与状态字段设计
- 使用
is_deleted或delete_flag标识逻辑删除状态 - 添加状态字段(如
status,audit_status)明确当前业务状态
设计一个安全的数据库
1. 添加审计字段
created_time,updated_time:用于追踪数据变更created_by,updated_by(或user_name):记录操作人员信息
2. 字段设计细节中的数据安全与可读性
| 项目 | 建议 |
|---|---|
| 字段类型 | 精确选择(如金额用 DECIMAL,状态用 TINYINT) |
| 字段长度 | 合理限制(如用户名不超过 50 字符) |
| 是否可空 | 关键字段设置为 NOT NULL |
| 默认值 | 避免出现 NULL |
| 时间字段 | 统一使用 created_time, updated_time 命名 |
3. 数据权限与信息安全
- 用户权限采用分级管理(如管理员、普通用户)
- 对敏感字段(如手机号、身份证)进行加密或脱敏处理
- 使用数据库层访问控制(如视图、只读账号)
对自己的一段话
想着什么都顾及上,最后只会极其臃肿且不合理。数据库的设计并非一蹴而就,在项目的不同阶段,可能需要根据业务变化进行优化与调整。初期尽量遵循三范式,随着业务复杂度提升,再根据性能、扩展性、安全性逐步反范式化或重构。
欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1701220998@qq.com