# 数据库设计

## 规则（Rules）

# 数据库设计规范

## 适用对象和范围

本规范适用于所有设计数据库模型的场景，包括表结构设计、索引优化、关系设计和SQL编写。

---

## 1. 表名规范

**规则**：表名必须使用小写蛇形（snake_case），单数形式。

- ✅ 正确：`user_accounts`、`order_items`、`product_categories`
- ❌ 错误：`UserAccounts`、`userAccounts`、`users`（复数）

**违反后果**：表名不规范导致SQL语句可读性差，与ORM默认映射冲突。

---

## 2. 字段名规范

**规则**：字段名必须使用小写蛇形（snake_case）。

- ✅ 正确：`user_name`、`created_at`、`is_active`
- ❌ 错误：`userName`、`createdAt`、`isActive`

**违反后果**：字段名不规范导致SQL语句可读性差。

---

## 3. 主键规范

**规则**：每个表必须有主键，通常为自增INT或UUID。

- ✅ 正确：`id INT AUTO_INCREMENT PRIMARY KEY`
- ❌ 错误：无主键或使用业务字段做主键

**违反后果**：无主键导致数据无法唯一标识，影响数据操作和性能。

---

## 4. 数据库规范化

**规则**：数据库设计必须满足至少第三范式（3NF），禁止存储冗余数据。

- ✅ 正确：用户信息存在 `users` 表，订单信息存在 `orders` 表，通过 `user_id` 关联
- ❌ 错误：在 `orders` 表中同时存储 `user_name`、`user_email` 等用户信息

**违反后果**：冗余数据导致数据不一致（更新异常），浪费存储空间。

---

## 5. 索引策略规范

**规则**：必须为以下字段创建索引：
- 主键（自动创建）
- 业务唯一字段（创建唯一索引）
- 经常作为查询条件的字段（创建普通索引）
- 多条件查询的字段组合（创建复合索引）

- ✅ 正确：为 `email` 创建唯一索引，为 `status` 创建普通索引
- ❌ 错误：不为查询字段创建索引

**违反后果**：缺少索引导致查询性能差，大数据量时响应缓慢。

---

## 6. 外键规范

**规则**：关联其他表的字段必须注明参照关系，命名使用 `{参照表名}_id`。

- ✅ 正确：`user_id`（参照 users 表）、`order_id`（参照 orders 表）
- ❌ 错误：`uid`、`oid`（含义不明确）

**违反后果**：外键命名不明确导致表关系难以理解。

---

## 7. 字段类型规范

**规则**：字段类型必须根据实际数据选择，避免过度使用大类型。

| 数据类型 | 适用场景 |
|---------|---------|
| INT/BIGINT | 整数ID、计数 |
| VARCHAR(n) | 变长字符串，n为最大长度 |
| TEXT | 长文本（超过VARCHAR上限） |
| DATETIME/TIMESTAMP | 日期时间 |
| DECIMAL(m,n) | 金额等精确小数 |
| TINYINT | 布尔值（0/1） |

- ✅ 正确：状态用 `TINYINT`，姓名用 `VARCHAR(50)`，金额用 `DECIMAL(10,2)`
- ❌ 错误：状态用 `VARCHAR(255)`，金额用 `FLOAT`

**违反后果**：字段类型选择不当导致存储浪费或精度丢失。

## 方法（Methods）

# 数据库设计方法

## 前置条件

- [ ] 已获取需求文档，了解数据实体和关系
- [ ] 已获取架构设计文档（如有）

## 流程概览

分析数据需求 → 设计表结构 → 设计索引策略 → 编写SQL建表脚本 → 输出数据库设计文档

## 详细步骤

### 步骤1：分析数据需求
分析需求文档，提取数据实体和关系。分析架构设计文档（若存在），提取数据字段需求。

### 步骤2：设计表结构
对每个实体，设计数据库表：
- 表名：snake_case格式
- 字段：包含字段名、类型、长度、是否为空、默认值

## 技巧（Tips）

# 数据库设计技巧

## 1. 使用ER图辅助设计

**适用场景**：需要理清多个实体之间的复杂关系时。

**具体做法**：先用文本描述实体关系，再设计表结构。

**示例**：
```text
用户(1) ----< 订单(N)   一个用户可以有多个订单
订单(1) ----< 订单项(N) 一个订单可以有多个商品
商品(1) ----< 订单项(N) 一个商品可以出现在多个订单中
```

**注意事项**：多对多关系需要中间表（关联表）来实现。

---

## 2. 合理使用索引

**适用场景**：需要优化查询性能时。

**具体做法**：根据查询场景选择合适的索引类型。

**对比说明**：

| 索引类型 | 适用场景 | 示例 |
|---------|---------|------|
| 主键索引 | 唯一标识 | id |
| 唯一索引 | 业务唯一字段 | email、id_card |
| 普通索引 | 查询条件字段 | status、category_id |
| 复合索引 | 多条件查询 | (status, created_at) |

**注意事项**：
- 复合索引遵循"最左前缀"原则
- 索引不是越多越好，写操作会受影响
- 小表（<1000行）不需要索引

---

## 3. 使用EXPLAIN分析查询

**适用场景**：需要排查SQL查询性能问题时。

**具体做法**：在SQL前加 `EXPLAIN` 查看执行计划。

**示例**：
```sql
EXPLAIN SELECT * FROM orders WHERE user_id = 100 AND status = 1;

-- 关注以下字段
-- type: ALL 表示全表扫描，需优化
-- possible_keys: 可能使用的索引
-- key: 实际使用的索引
-- rows: 扫描行数，越小越好
```

**注意事项**：`type=ALL` 或 `rows` 很大时，说明需要添加索引。

---

## 4. 常见问题速查

| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 查询速度慢 | 缺少索引或SQL写法不当 | 添加索引，优化SQL |
| 数据不一致 | 未使用事务或外键 | 添加事务控制和外键约束 |
| 死锁 | 事务顺序不一致 | 统一事务中的表操作顺序 |
| 存储空间增长快 | 字段类型过大或未归档 | 优化字段类型，定期归档历史数据 |
| 连接超时 | 连接池配置不当 | 调整连接池大小和超时时间 |
