数据库设计黄金规范:从命名到索引的系统化最佳实践

2025/11/6 实践总结最佳

# 1. 引言

本规范旨在统一数据库设计标准,保障数据一致性、完整性、性能与可维护性,适用于所有业务系统的数据库设计(如 MySQL、PostgreSQL 等关系型数据库),需结合业务场景灵活落地。

# 2. 命名规范

# 2.1 核心原则

  • 统一采用 “小写字母 + 下划线” 命名法,禁止混合大小写、特殊字符(如#$)或数据库关键字(如selectorder);

  • 所有命名需体现业务含义,避免无意义缩写或数字标识(如index1t1);

  • 表名、字段名、索引名长度控制在 30 字符内(避免超出数据库命名长度限制)。

# 2.2 各对象命名规范

对象类型 规范要求 正例 反例 反例问题
表名 业务模块前缀 + 核心含义(如user_order_ user_info(用户信息表)、order_detail(订单明细表) UserInfo(混合大小写)、order(无模块前缀 + 关键字) 协作理解成本高,需转义关键字
字段名 核心含义 + 统一后缀(如时间用_at、状态用_status user_id(用户 ID)、created_at(创建时间) uid(无意义缩写)、CreatedTime(驼峰命名) 新人需额外文档理解,命名不统一
索引名 类型标识(idx_普通索引 /uni_唯一索引)+ 字段组合 idx_user_id_status(用户 ID + 状态普通索引)、uni_user_phone(用户手机号唯一索引) index2(无含义)、user_index(无类型标识) 维护时无法快速判断索引用途
视图名 前缀view_+ 业务含义 view_user_order(用户订单关联视图) user_order_view(前缀不统一) 无法快速区分视图与表

# 3. 结构设计规范

# 3.1 范式与反范式平衡

  • 优先遵循第三范式:消除数据冗余与传递依赖(如用户手机号仅存于user_info,不冗余到order_detail);

  • 非核心场景适当反范式:高频查询表(如商品详情页)可冗余关联字段(如product表冗余category_name),减少 JOIN 操作,需通过定时任务 / 消息队列同步数据。

# 3.2 表拆分与扩展

规范要求 正例 反例 反例问题
大表拆分 订单表按时间分表:order_202501order_202502(单表数据≤1000 万) 单表存储 5 亿订单数据 查询耗时从 100ms 增至 5s,索引失效
字段扩展 预留扩展字段需注明用途:ext1 VARCHAR(64) COMMENT '预留:用户等级标识' 无注释的ext1ext2 后续维护无法判断字段用途,易滥用
附属表拆分 大字段(如用户头像、文章内容)拆分至附属表:user_avatar(存头像路径) 主表user_infoavatar BLOB字段 主表查询时加载大字段,性能下降

# 4. 字段设计规范

# 4.1 通用字段设计原则

  • 优先选择 “最小且合适” 的数据类型(如状态用TINYINT,不用INT);

  • 非必要字段不设NOT NULL,关键字段(如user_id)设默认值或非空约束;

  • 禁止用字符串存储日期、金额、状态等结构化数据。

# 4.2 常用字段专项规范

# 4.2.1 时间类常用字段

字段名 数据类型 适用场景 正例 反例 设计原则
created_at datetime(时区同步用timestamp 数据创建时间(用户注册、订单生成) created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP create_time VARCHAR(20)(存2025-11-06 统一用_at后缀,禁止字符串存储,设默认值
updated_at datetime 数据最后更新时间(订单状态修改) updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP update_time(无自动更新) 设 “更新时自动填充”,避免手动维护
deleted_at datetime 软删除标记(替代物理删除) deleted_at datetime DEFAULT NULL(未删除为NULL is_delete TINYINT(1)(仅存是否删除) 保留删除时间便于追溯,不用布尔型单独存储
expired_at datetime 过期时间(优惠券、会员有效期) expired_at datetime NOT NULL expire_date DATE(仅存日期,无时间) 需精确控制过期时间时用datetime

# 4.2.2 状态类常用字段

字段名 数据类型 适用场景 正例 反例 设计原则
status TINYINT UNSIGNED 通用状态(订单:0 = 未支付,1 = 已支付) status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0=未支付,1=已支付,2=已取消' status VARCHAR(10)(存 “未支付”) 用数字枚举 + 注释,禁止字符串存储
audit_status TINYINT UNSIGNED 审核状态(文章:0 = 待审核,1 = 通过) audit_status TINYINT UNSIGNED NOT NULL DEFAULT 0 check_status(命名不统一) 业务场景 +_status,避免自定义模糊命名
is_valid TINYINT(1) 数据有效性(0 = 无效,1 = 有效) is_valid TINYINT(1) NOT NULL DEFAULT 1 is_active/is_enable(混用) 布尔型状态统一用is_+形容词

# 4.2.3 关联类常用字段

字段名 数据类型 适用场景 正例 反例 设计原则
user_id user_info.id一致(如BIGINT 关联用户表 user_id BIGINT NOT NULL COMMENT '关联user_info.id' uid INT(缩写 + 类型不匹配) 关联表名 +_id,类型与被关联主键一致
parent_id 与当前表id一致 自关联(分类上下级、评论回复) parent_id BIGINT DEFAULT 0 COMMENT '父分类ID,0=顶级' pid(缩写) 自关联固定用parent_id

# 4.2.4 标识 / 描述类常用字段

字段名 数据类型 适用场景 正例 反例 设计原则
id BIGINT UNSIGNED 表主键(自增) id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY user_id(主键名不统一) 单表主键固定用id,自增 + 无符号
uuid CHAR(36) 全局唯一标识(分布式系统) uuid CHAR(36) NOT NULL COMMENT '全局唯一UUID' uuid VARCHAR(50)(长度冗余) CHAR(36)(UUID 标准长度)
remark VARCHAR(512) 备注(订单备注、操作说明) remark VARCHAR(512) DEFAULT '' COMMENT '用户订单备注' remark TEXT(大字段滥用) 内容≤1000 字用VARCHAR,避免TEXT

# 5. 索引设计规范

# 5.1 核心原则

  • 主键必设(优先自增BIGINT,避免UUID导致索引碎片化);

  • 单表索引数量≤5 个(过多索引导致写入性能下降 30%+);

  • 联合索引遵循 “最左前缀原则”,高频查询字段放左侧。

# 5.2 索引设计

场景 正例 反例 反例问题
高频查询 登录验证:uni_user_phone(手机号唯一索引) user_infogender(性别,区分度低)建索引 扫描行数占比高,索引无效
联合索引 订单查询:idx_user_id_created_at(用户 ID + 创建时间) idx_create_at_user_id(高频字段在后) 无法命中 “用户 ID + 时间范围” 查询
避免失效 时间范围查询:created_at BETWEEN '2025-11-01' AND '2025-11-06' DATE_FORMAT(create_at, '%Y-%m') = '2025-11' 函数操作导致索引失效,全表扫描

# 6. 完整性约束规范

约束类型 规范要求 正例 反例 反例问题
主键约束 单表唯一主键,自增BIGINT id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY 无主键或用UUID做主键 无主键导致数据无法唯一定位,UUID影响性能
外键约束 核心表(如order关联user)用外键,高频更新表(如社交好友表)应用层校验 user_id BIGINT NOT NULL REFERENCES user_info(id) 所有表均无外键,应用层未校验 数据不一致(如删除用户后残留订单)
唯一约束 需去重字段(手机号、商品编码)加唯一索引 uni_user_phone(手机号唯一索引) 业务层判断去重,无数据库约束 高并发下导致重复数据
CHECK 约束 字段合法性校验(如年龄 1-120 岁) age TINYINT UNSIGNED CHECK (age BETWEEN 1 AND 120) 仅应用层校验年龄 绕过应用层操作时插入非法数据

# 7. 性能与安全规范

规范维度 要求 正例 反例 反例问题
存储引擎 优先InnoDB(支持事务、行锁),日志表可MyISAM user_infoInnoDBsys_logMyISAM 混合引擎(userInnoDBorderMyISAM 跨表事务不支持,数据一致性风险
敏感数据 加密存储(密码哈希,手机号脱敏) 密码:SHA-256加盐哈希;手机号:`SUBSTR (phone,1,3)
分库分表 数据量超 1000 万规划拆分(按时间、地域、用户 ID 哈希) 订单表按用户 ID 哈希分 3 库 10 表 单库单表存储 5 亿数据 连接超时,查询无法响应

# 8. 规范落地建议

  1. 设计前校验:使用 “数据库设计校验清单”(含命名、字段类型、索引数量等),避免遗漏;

  2. 定期评审:每季度检查线上表结构,删除冗余索引、清理无用字段;

  3. 工具辅助:用 SQL lint 工具(如sqlfluff)自动检测命名与类型规范,集成到 CI/CD 流程;

  4. 文档同步:表结构变更需更新文档,记录字段含义、约束规则及变更原因。