Administrator
Administrator
发布于 2025-08-29 / 5 阅读

数据库设计规范

以下是一些在业界广泛认可和采用的数据库设计最佳实践与建议:


一、 基础与核心原则

  1. 清晰一致的命名规范

    • 表名、列名: 使用蛇形命名法snake_case),如 user_id, created_at。保持全局一致。
    • 表名: 使用复数名词,如 users, orders,表示这是一个集合。
    • 关联表: 使用两个表名的单数形式拼接,如 user_roles
    • 布尔字段: 使用 is_, has_, can_ 等前缀,如 is_active, has_verified
    • 避免使用保留字:order, user, key 等,如果必须使用,请用反引号包裹。
  2. 选择合适的字段类型

    • 越小越好: 能用 SMALLINT 就不用 INT,能用 VARCHAR(255) 就不用 TEXT。节省存储,提高操作速度。
    • 精确数字: 金额、金融相关数据使用 DECIMAL,避免使用 FLOATDOUBLE 以免产生精度损失。
    • 时间日期: 始终使用 DATETIMETIMESTAMP 来存储时间。TIMESTAMP 会带时区转换,需注意。统一使用 UTC 时间存储在数据库中,在前端显示时再转换为用户本地时间。
    • 枚举字段: 优先使用 ENUM 类型或关联字典表,而不是存储魔法数字(magic number)如 status = 1。或者在应用层定义常量。
  3. 范式与反范式的权衡

    • 范式化 (Normalization): 减少数据冗余,保证数据一致性。这是设计的基础。
    • 反范式化 (Denormalization): 为了性能,可以有意识地引入冗余。 例如,在“订单表”里冗余“用户名”,避免每次查订单都要 JOIN 用户表。这是一种 “用空间换时间” 的策略。
    • 建议: 先遵循范式化设计,然后在明确的性能瓶颈出现时,再有选择地进行反范式化优化。

二、 表与关系设计

  1. 每个表都必须有主键

    • 通常使用 INTBIGINT 自增主键(代理主键),除非有极特殊理由,否则不要用业务字段作为主键(自然主键)。
    • 优点: 与业务解耦,稳定,且 INT 性能极佳。
  2. 使用外键约束 (Foreign Key)

    • 强烈建议在项目初期使用外键。 它能保证数据的参照完整性,避免产生“脏数据”和“孤儿记录”。
    • 注意: 在高并发、超大规模互联网业务中,有时会在应用层通过逻辑保证一致性,而不用数据库外键,以提升写入性能。但这对开发者的要求极高,不建议初学者放弃外键
  3. 多对多关系使用关联表

    • 正如我们之前讨论的,任何多对多关系都必须通过一个中间关联表来实现,该表至少包含两个外键字段。
  4. 添加公共字段

    • 几乎所有表都应包含以下字段,用于审计和排查问题:
      • id : BIGINT 自增主键。
      • created_at : TIMESTAMP 默认 CURRENT_TIMESTAMP
      • updated_at : TIMESTAMP 默认 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(MySQL)。
      • (可选)deleted_at : TIMESTAMP 默认 NULL。用于实现软删除,标记删除时间而非真正删除记录,数据更安全。

三、 性能与可维护性

  1. 为查询创建索引,但不要过度索引

    • 法则:WHERE 条件、 ORDER BYGROUP BYJOIN 子句中频繁出现的列上创建索引。
    • 前缀索引: 对很长的 VARCHAR 字段,可以只索引前一部分字符(如 title(50))。
    • 联合索引: 注意最左前缀匹配原则。查询 (a, b, c) 联合索引时,必须从最左边的列开始匹配。
    • 代价: 索引会降低 INSERT, UPDATE, DELETE 的速度,并占用额外空间。监控并删除从未被使用过的索引。
  2. 考虑数据归档与分区

    • 对于像聊天记录、操作日志等会无限增长的表,在设计之初就要考虑数据生命周期。
    • 方法:
      • 分区 (Partitioning): 按时间(如每月一个分区)对大数据表进行分区,可以极大提升历史查询和删除旧数据的效率。
      • 归档 (Archiving): 定期将冷数据(如一年前的订单)迁移到另一个归档数据库中,保证主库的轻量和高效。
  3. 避免全表扫描

    • 通过 EXPLAIN 命令分析你的 SELECT 查询语句,确保它们有效地使用了索引,而不是进行全表扫描(type=ALL),尤其是在大表上。

四、 安全与扩展

  1. 永远不要明文存储密码

    • 使用强度高的哈希算法(如 bcryptArgon2)进行哈希并加盐(salt)处理,然后将哈希值存入数据库。绝对禁止使用明文或简单的 MD5 存储。
  2. 敏感信息加密

    • 对于用户身份证号、手机号、银行卡号等极度敏感的信息,可以考虑在入库前在应用层进行加密,或者使用数据库提供的加密功能。
  3. 文档化

    • 使用工具(如 dbdiagram.io)绘制 ER(实体关系)图
    • 在数据库中为表、列添加注释(COMMENT)。数据字典是团队最重要的财富之一。
  4. 使用迁移工具管理结构变更

    • 不要手动在生产环境数据库上执行 ALTER TABLE。使用像 LiquibaseFlyway 这样的数据库迁移工具,让所有结构变更(DDL)都通过版本化的脚本进行,实现可追溯、可回滚的自动化部署。

总结清单

类别 建议 说明
命名 蛇形命名,表名复数,布尔加前缀 保持一致性,提高可读性
字段 类型越小越好,金额用DECIMAL,时间用UTC 保证精度,节省空间
设计 每个表都有主键,多用外键,公共字段(created_at) 保证数据完整性和可追溯性
范式 先范式化,再按需反范式化 在一致性和性能间取得平衡
性能 为查询创建索引,避免全表扫描,规划归档策略 保证系统长期高性能运行
安全 密码哈希加盐,敏感信息加密 保护用户数据安全是底线
维护 绘制ER图,使用迁移工具管理变更 提升团队协作效率和系统可维护性

遵循这些实践,您的数据库设计就已经超越了大多数项目,为一个稳健、可扩展的后端系统打下了坚实的基础。