MySQL:库表设计完整规范与实战方案

一、整体设计原则(优先遵守)

1、范式适度:基础遵循第三范式,高频关联查询场景允许适当冗余,避免过度范式导致大量 JOIN;

2、冷热分离:大日志、历史归档数据单独分表 / 分库;

3、索引先行:建表同时规划索引,禁止后期随意新增大索引;

4、兼容扩展:预留扩展字段,禁止硬编码字段含义;

5、字符集统一推荐 utf8mb4 ,支持 emoji;排序规则 utf8mb4_unicode_ci

6、引擎统一 :业务表默认 InnoDB(事务、行锁、外键可选);日志临时表可考虑 MyISAM(极少场景)。
❌ 避坑:不要使用 utf8(mysql utf8 ≠ utf8,最多 3 字节,不支持表情)

二、数据库(Schema)设计规范

1. 库命名规范

小写字母 + 下划线,禁止大写、中文、特殊符号

格式:业务模块_db 示例:order_dbuser_dbgoods_db

2. 库参数标准配置(建库语句)

复制代码
CREATE DATABASE IF NOT EXISTS user_db
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;

3. 分库策略简单区分

垂直分库:按业务拆分(用户库、订单库、商品库)

水平分库:单库数据量过大,同一张表拆分到多个库

三、数据表设计规范

1. 表名规范

小写、下划线,名词复数形式

格式:模块_表名 示例:user_infoorder_mainorder_item

禁止:UserInfouserInfo用户表

2. 必备标准字段(所有业务表建议统一带上)

|-------------|-------------------------------------------------------------------------|----------------------------|
| 字段名 | 类型 | 说明 |
| id | bigint unsigned NOT NULL | 主键自增主键(雪花 ID 可选,分布式) |
| create_time | datetime NOT NULL DEFAULT CURRENT_TIMESTAMP | 创建时间 |
| update_time | datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间,自动刷新 |
| is_deleted | tinyint NOT NULL DEFAULT 0 | 逻辑删除:0 正常,1 删除(禁止物理删除) |

分布式系统:不建议自增主键,改用 BIGINT 雪花算法 ID

3. 字段类型选型最佳实践

数字类型

主键 ID:bigint unsigned(不要 int,数据量容易溢出)

状态标识:tinyint 0/1/2/3(不要 char/varchar 存状态)

金额:DECIMAL(m,n) ,严禁 float/double(浮点精度丢失) 例:decimal(12,2) 最多千万级金额,保留 2 位小数

普通数量:int;超大数量用 bigint

字符串类型

短标识、编码:varchar(32) / varchar(64)

名称、标题:varchar(255)

超长文本、备注:text(尽量少用,无法建立普通索引)
varchar 长度够用即可,不要统一全部 255

时间类型

时间点:datetime(推荐,可读性强,不受时区影响)

仅日期:date

仅时分秒:time
不推荐使用 timestamp(时区限制、2038 上限)

布尔逻辑

不用 bool,统一 tinyint(1) 0 = 否,1 = 是

4. 字段命名规范

小写下划线,见名知意 user_namephoneorder_amount

状态统一后缀 _status order_statuspay_status

数量统一后缀 _num buy_num

5. 约束规范

1、主键 PRIMARY KEY 单一主键优先 id;尽量避免联合主键

2、唯一索引 UNIQUE 手机号、用户名、订单号等唯一字段

3、NOT NULL 优先 能不为 NULL 尽量 NOT NULL,设置默认值;NULL 查询会带来额外开销

4、谨慎使用外键 InnoDB 支持外键,但高并发业务不推荐,由应用程序保证数据一致性

四、索引设计规范(重中之重)

1. 索引分类

主键索引:PRIMARY KEY(id)

普通索引:单字段 / 联合索引

唯一索引:UNIQUE KEY uk_phone(phone)

前缀索引:超长字符串使用(如 url)

2. 联合索引最左匹配原则

建立 idx_name_status(user_name, order_status)

✅ 可以命中:where user_name=? / where user_name=? and order_status=?

❌ 无法命中:where order_status=?

3. 索引避坑清单

1、不要在低基数字段单独建索引(如性别、is_deleted)

2、索引字段禁止函数操作:where DATE(create_time)='xxx' → 失效

3、不要超量建索引:写入(insert/update/delete)会同步维护索引

4、字符串匹配禁止左模糊 like '%xxx',索引失效;like 'xxx%' 可行

五、完整建表示例

用户主表 user_info

复制代码
CREATE TABLE `user_info` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `user_name` varchar(64) NOT NULL COMMENT '用户名',
  `phone` varchar(32) NOT NULL COMMENT '手机号',
  `password` varchar(128) NOT NULL COMMENT '加密密码',
  `user_status` tinyint NOT NULL DEFAULT 1 COMMENT '用户状态 0禁用 1正常',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除 0未删 1已删',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_phone` (`phone`),
  KEY `idx_user_status` (`user_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表';

订单主表 order_main

复制代码
CREATE TABLE `order_main` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '订单主键',
  `order_no` varchar(64) NOT NULL COMMENT '订单编号',
  `user_id` bigint unsigned NOT NULL COMMENT '用户id',
  `order_amount` decimal(12,2) NOT NULL DEFAULT 0.00 COMMENT '订单金额',
  `order_status` tinyint NOT NULL DEFAULT 0 COMMENT '订单状态',
  `pay_status` tinyint NOT NULL DEFAULT 0 COMMENT '支付状态',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `is_deleted` tinyint NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`),
  KEY `idx_userid_status` (`user_id`,`order_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单主表';

订单明细表 order_item(一对多拆分)

规范:主表存订单整体信息,明细表存储多条商品,禁止用逗号拼接商品 ID 存在一个字段

复制代码
CREATE TABLE `order_item` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `order_id` bigint unsigned NOT NULL COMMENT '订单主表id',
  `goods_id` bigint unsigned NOT NULL COMMENT '商品id',
  `goods_name` varchar(255) NOT NULL COMMENT '商品名称快照',
  `price` decimal(12,2) NOT NULL COMMENT '下单单价',
  `buy_num` int NOT NULL DEFAULT 1 COMMENT '购买数量',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `is_deleted` tinyint NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单明细表';

六、常用设计最佳实践

1、一对多关系 用户 1 → 订单 N:订单表保存 user_id

2、多对多关系 用户 <-> 角色:新建中间表 user_role_rel,存储 user_id、role_id,联合唯一索引

3、字典 / 常量 状态含义不要写死在 SQL 注释,建议建立字典表 sys_dict,代码读取

4、大文本 文章正文、富文本单独一张表,避免主表查询加载大字段

5、分页查询 尽量基于有序索引字段分页,避免 limit 1000000,10 深度分页

七、开发规范红线(禁止操作)

1、❌ 表、字段使用中文;

2、❌ 使用 TEXT/BLOB 建立普通索引;

3、❌ 使用 float/double 存储金额;

4、❌ 大量使用 NULL,不设置默认值;

5、❌ 业务数据物理 DELETE;

6、❌ 一条字段存储多条数据(逗号分隔 id);

7、❌ 随意创建联合索引,不遵守最左前缀;

8、❌ 在线业务直接执行 ALTER TABLE 锁表操作。

八、延伸方案

数据量大:水平分表(按 user_id 哈希、时间范围分表)

读写压力高:主从分离,读走从库

海量日志:时序表、按月分区表 PARTITION BY RANGE

相关推荐
ACP广源盛139246256732 小时前
WAIC2026 国产算力浪潮下@ACP#IX8024 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵
ClouGence2 小时前
数据库管理工具 CloudDM 4.1.0 发布,支持达梦、Cloudberry
数据库·开源
小白勇闯网安圈2 小时前
Django 模板复用、ORM 查询与多对多关系
数据库·python·django
TELL5213 小时前
帮我生成对应的sql 以及数据库-deepseek提示词
数据库·sql
能年玲奈喝榴莲牛奶3 小时前
系统规划与管理师-第一章-考点记忆
大数据·数据库·软考·系统规划与管理师·系规
SatanII3 小时前
mariadb
数据库·mariadb
大千UI工场4 小时前
时序数据库对数字孪生的作用
数据库·ui·时序数据库·前端开发·b端管理系统
Tongzhi20264 小时前
通芝科技无感考勤一体机:软硬一体,开箱即用
数据结构·数据库·科技·算法·均值算法·数据库开发
这就是佬们吗4 小时前
向量数据库选型与实战:从原理到生产环境的完整指南
数据库