database-schema-designer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDatabase Schema Designer
数据库架构设计工具
Design production-ready database schemas with best practices built-in.
设计符合最佳实践的生产级数据库架构。
Quick Start
快速开始
Just describe your data model:
design a schema for an e-commerce platform with users, products, ordersYou'll get a complete SQL schema like:
sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
total DECIMAL(10,2) NOT NULL,
INDEX idx_orders_user (user_id)
);What to include in your request:
- Entities (users, products, orders)
- Key relationships (users have orders, orders have items)
- Scale hints (high-traffic, millions of records)
- Database preference (SQL/NoSQL) - defaults to SQL if not specified
只需描述你的数据模型:
design a schema for an e-commerce platform with users, products, orders你将得到完整的SQL架构,例如:
sql
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
total DECIMAL(10,2) NOT NULL,
INDEX idx_orders_user (user_id)
);请求中需包含的内容:
- 实体(用户、商品、订单等)
- 关键关系(用户拥有订单、订单包含商品项等)
- 规模提示(高流量、百万级记录等)
- 数据库偏好(SQL/NoSQL)- 未指定时默认使用SQL
Triggers
触发词
| Trigger | Example |
|---|---|
| "design a schema for user authentication" |
| "database design for multi-tenant SaaS" |
| "create tables for a blog system" |
| "schema for inventory management" |
| "model data for real-time analytics" |
| "I need a database for tracking orders" |
| "design NoSQL schema for product catalog" |
| 触发词 | 示例 |
|---|---|
| "design a schema for user authentication" |
| "database design for multi-tenant SaaS" |
| "create tables for a blog system" |
| "schema for inventory management" |
| "model data for real-time analytics" |
| "I need a database for tracking orders" |
| "design NoSQL schema for product catalog" |
Key Terms
关键术语
| Term | Definition |
|---|---|
| Normalization | Organizing data to reduce redundancy (1NF → 2NF → 3NF) |
| 3NF | Third Normal Form - no transitive dependencies between columns |
| OLTP | Online Transaction Processing - write-heavy, needs normalization |
| OLAP | Online Analytical Processing - read-heavy, benefits from denormalization |
| Foreign Key (FK) | Column that references another table's primary key |
| Index | Data structure that speeds up queries (at cost of slower writes) |
| Access Pattern | How your app reads/writes data (queries, joins, filters) |
| Denormalization | Intentionally duplicating data to speed up reads |
| 术语 | 定义 |
|---|---|
| Normalization(规范化) | 组织数据以减少冗余(1NF → 2NF → 3NF) |
| 3NF | 第三范式 - 列之间不存在传递依赖 |
| OLTP | 在线事务处理 - 写密集型场景,需采用规范化设计 |
| OLAP | 在线分析处理 - 读密集型场景,采用反规范化设计更有利 |
| Foreign Key (FK)(外键) | 引用另一张表主键的列 |
| Index(索引) | 加速查询的数据结构(会降低写入速度) |
| Access Pattern(访问模式) | 应用读写数据的方式(查询、关联、过滤等) |
| Denormalization(反规范化) | 为加速读取而故意重复数据 |
Quick Reference
快速参考
| Task | Approach | Key Consideration |
|---|---|---|
| New schema | Normalize to 3NF first | Domain modeling over UI |
| SQL vs NoSQL | Access patterns decide | Read/write ratio matters |
| Primary keys | INT or UUID | UUID for distributed systems |
| Foreign keys | Always constrain | ON DELETE strategy critical |
| Indexes | FKs + WHERE columns | Column order matters |
| Migrations | Always reversible | Backward compatible first |
| 任务 | 方法 | 关键注意事项 |
|---|---|---|
| 新架构设计 | 先规范化到3NF | 优先领域建模而非UI建模 |
| SQL vs NoSQL选择 | 由访问模式决定 | 读写比是关键因素 |
| 主键选择 | INT或UUID | 分布式系统使用UUID |
| 外键 | 始终添加约束 | ON DELETE策略至关重要 |
| 索引 | 外键+WHERE条件列 | 列的顺序很重要 |
| 架构迁移 | 始终支持回滚 | 优先保证向后兼容 |
Process Overview
流程概述
Your Data Requirements
|
v
+-----------------------------------------------------+
| Phase 1: ANALYSIS |
| * Identify entities and relationships |
| * Determine access patterns (read vs write heavy) |
| * Choose SQL or NoSQL based on requirements |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Phase 2: DESIGN |
| * Normalize to 3NF (SQL) or embed/reference (NoSQL) |
| * Define primary keys and foreign keys |
| * Choose appropriate data types |
| * Add constraints (UNIQUE, CHECK, NOT NULL) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Phase 3: OPTIMIZE |
| * Plan indexing strategy |
| * Consider denormalization for read-heavy queries |
| * Add timestamps (created_at, updated_at) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Phase 4: MIGRATE |
| * Generate migration scripts (up + down) |
| * Ensure backward compatibility |
| * Plan zero-downtime deployment |
+-----------------------------------------------------+
|
v
Production-Ready Schema你的数据需求
|
v
+-----------------------------------------------------+
| 阶段1:分析 |
| * 识别实体和关系 |
| * 确定访问模式(读密集型 vs 写密集型) |
| * 根据需求选择SQL或NoSQL |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| 阶段2:设计 |
| * SQL规范化到3NF,NoSQL选择嵌入/引用 |
| * 定义主键和外键 |
| * 选择合适的数据类型 |
| * 添加约束(UNIQUE、CHECK、NOT NULL) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| 阶段3:优化 |
| * 规划索引策略 |
| * 读密集型查询考虑反规范化 |
| * 添加时间戳(created_at、updated_at) |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| 阶段4:迁移 |
| * 生成迁移脚本(升级+回滚) |
| * 确保向后兼容 |
| * 规划零停机部署 |
+-----------------------------------------------------+
|
v
生产级可用架构Commands
命令
| Command | When to Use | Action |
|---|---|---|
| Starting fresh | Full schema generation |
| Fixing existing table | Apply normalization rules |
| Performance issues | Generate index strategy |
| Schema evolution | Create reversible migration |
| Code review | Audit existing schema |
Workflow: Start with → iterate with → optimize with → evolve with
design schemanormalizeadd indexesmigration| 命令 | 使用场景 | 操作 |
|---|---|---|
| 从零开始设计 | 生成完整架构 |
| 修复现有表 | 应用规范化规则 |
| 存在性能问题 | 生成索引策略 |
| 架构演进 | 创建支持回滚的迁移脚本 |
| 代码评审 | 审计现有架构 |
工作流: 从开始 → 用迭代 → 用优化 → 用演进
design schemanormalizeadd indexesmigrationCore Principles
核心原则
| Principle | WHY | Implementation |
|---|---|---|
| Model the Domain | UI changes, domain doesn't | Entity names reflect business concepts |
| Data Integrity First | Corruption is costly to fix | Constraints at database level |
| Optimize for Access Pattern | Can't optimize for both | OLTP: normalized, OLAP: denormalized |
| Plan for Scale | Retrofitting is painful | Index strategy + partitioning plan |
| 原则 | 原因 | 实现方式 |
|---|---|---|
| 领域建模优先 | UI会变化,但领域不会 | 实体名称反映业务概念 |
| 数据完整性优先 | 数据损坏修复成本极高 | 在数据库层面添加约束 |
| 针对访问模式优化 | 无法同时兼顾所有场景 | OLTP用规范化,OLAP用反规范化 |
| 提前规划扩展性 | 后期改造难度大 | 索引策略+分区规划 |
Anti-Patterns
反模式
| Avoid | Why | Instead |
|---|---|---|
| VARCHAR(255) everywhere | Wastes storage, hides intent | Size appropriately per field |
| FLOAT for money | Rounding errors | DECIMAL(10,2) |
| Missing FK constraints | Orphaned data | Always define foreign keys |
| No indexes on FKs | Slow JOINs | Index every foreign key |
| Storing dates as strings | Can't compare/sort | DATE, TIMESTAMP types |
| SELECT * in queries | Fetches unnecessary data | Explicit column lists |
| Non-reversible migrations | Can't rollback | Always write DOWN migration |
| Adding NOT NULL without default | Breaks existing rows | Add nullable, backfill, then constrain |
| 需避免的做法 | 原因 | 替代方案 |
|---|---|---|
| 到处使用VARCHAR(255) | 浪费存储空间,无法明确字段用途 | 根据字段实际需求设置合适长度 |
| 用FLOAT存储金额 | 会出现舍入误差 | 使用DECIMAL(10,2) |
| 缺失外键约束 | 会产生孤立数据 | 始终定义外键 |
| 外键上未加索引 | 关联查询缓慢 | 为所有外键添加索引 |
| 用字符串存储日期 | 无法比较/排序 | 使用DATE、TIMESTAMP类型 |
| 查询中使用SELECT * | 会获取不必要的数据 | 显式指定列名 |
| 不支持回滚的迁移 | 无法回滚到之前的状态 | 始终编写DOWN迁移脚本 |
| 添加NOT NULL约束但无默认值 | 会破坏现有数据行 | 先添加可空列,回填数据后再设置约束 |
Verification Checklist
验证清单
After designing a schema:
- Every table has a primary key
- All relationships have foreign key constraints
- ON DELETE strategy defined for each FK
- Indexes exist on all foreign keys
- Indexes exist on frequently queried columns
- Appropriate data types (DECIMAL for money, etc.)
- NOT NULL on required fields
- UNIQUE constraints where needed
- CHECK constraints for validation
- created_at and updated_at timestamps
- Migration scripts are reversible
- Tested on staging with production data
<details> <summary><strong>Deep Dive: Normalization (SQL)</strong></summary>
设计完架构后,请检查:
- 每张表都有主键
- 所有关系都定义了外键约束
- 每个外键都指定了ON DELETE策略
- 所有外键都有对应的索引
- 频繁查询的列都有索引
- 使用了合适的数据类型(如金额用DECIMAL)
- 必填字段设置了NOT NULL
- 需要唯一值的字段设置了UNIQUE约束
- 添加了CHECK约束用于验证
- 包含created_at和updated_at时间戳
- 迁移脚本支持回滚
- 已在 staging 环境用生产数据测试
<details> <summary><strong>深入解析:SQL规范化</strong></summary>
Normal Forms
范式
| Form | Rule | Violation Example |
|---|---|---|
| 1NF | Atomic values, no repeating groups | |
| 2NF | 1NF + no partial dependencies | customer_name in order_items |
| 3NF | 2NF + no transitive dependencies | country derived from postal_code |
| 范式 | 规则 | 违反示例 |
|---|---|---|
| 1NF | 原子值,无重复组 | |
| 2NF | 满足1NF且无部分依赖 | order_items表中包含customer_name |
| 3NF | 满足2NF且无传递依赖 | customer表中country由postal_code推导得出 |
1st Normal Form (1NF)
第一范式(1NF)
sql
-- BAD: Multiple values in column
CREATE TABLE orders (
id INT PRIMARY KEY,
product_ids VARCHAR(255) -- '101,102,103'
);
-- GOOD: Separate table for items
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT REFERENCES orders(id),
product_id INT
);sql
-- 错误:列中包含多个值
CREATE TABLE orders (
id INT PRIMARY KEY,
product_ids VARCHAR(255) -- '101,102,103'
);
-- 正确:拆分到单独的表
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT REFERENCES orders(id),
product_id INT
);2nd Normal Form (2NF)
第二范式(2NF)
sql
-- BAD: customer_name depends only on customer_id
CREATE TABLE order_items (
order_id INT,
product_id INT,
customer_name VARCHAR(100), -- Partial dependency!
PRIMARY KEY (order_id, product_id)
);
-- GOOD: Customer data in separate table
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(100)
);sql
-- 错误:customer_name仅依赖于customer_id
CREATE TABLE order_items (
order_id INT,
product_id INT,
customer_name VARCHAR(100), -- 部分依赖!
PRIMARY KEY (order_id, product_id)
);
-- 正确:客户数据存到单独的表
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(100)
);3rd Normal Form (3NF)
第三范式(3NF)
sql
-- BAD: country depends on postal_code
CREATE TABLE customers (
id INT PRIMARY KEY,
postal_code VARCHAR(10),
country VARCHAR(50) -- Transitive dependency!
);
-- GOOD: Separate postal_codes table
CREATE TABLE postal_codes (
code VARCHAR(10) PRIMARY KEY,
country VARCHAR(50)
);sql
-- 错误:country依赖于postal_code
CREATE TABLE customers (
id INT PRIMARY KEY,
postal_code VARCHAR(10),
country VARCHAR(50) -- 传递依赖!
);
-- 正确:拆分postal_codes表
CREATE TABLE postal_codes (
code VARCHAR(10) PRIMARY KEY,
country VARCHAR(50)
);When to Denormalize
何时使用反规范化
| Scenario | Denormalization Strategy |
|---|---|
| Read-heavy reporting | Pre-calculated aggregates |
| Expensive JOINs | Cached derived columns |
| Analytics dashboards | Materialized views |
sql
-- Denormalized for performance
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
total_amount DECIMAL(10,2), -- Calculated
item_count INT -- Calculated
);| 场景 | 反规范化策略 |
|---|---|
| 读密集型报表 | 预计算聚合值 |
| 关联查询成本高 | 缓存派生列 |
| 分析仪表板 | 物化视图 |
sql
-- 为性能优化的反规范化设计
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
total_amount DECIMAL(10,2), -- 计算得出
item_count INT -- 计算得出
);String Types
字符串类型
| Type | Use Case | Example |
|---|---|---|
| CHAR(n) | Fixed length | State codes, ISO dates |
| VARCHAR(n) | Variable length | Names, emails |
| TEXT | Long content | Articles, descriptions |
sql
-- Good sizing
email VARCHAR(255)
phone VARCHAR(20)
country_code CHAR(2)| 类型 | 使用场景 | 示例 |
|---|---|---|
| CHAR(n) | 固定长度 | 州代码、ISO日期 |
| VARCHAR(n) | 可变长度 | 姓名、邮箱 |
| TEXT | 长内容 | 文章、描述 |
sql
-- 合理设置长度
email VARCHAR(255)
phone VARCHAR(20)
country_code CHAR(2)Numeric Types
数值类型
| Type | Range | Use Case |
|---|---|---|
| TINYINT | -128 to 127 | Age, status codes |
| SMALLINT | -32K to 32K | Quantities |
| INT | -2.1B to 2.1B | IDs, counts |
| BIGINT | Very large | Large IDs, timestamps |
| DECIMAL(p,s) | Exact precision | Money |
| FLOAT/DOUBLE | Approximate | Scientific data |
sql
-- ALWAYS use DECIMAL for money
price DECIMAL(10, 2) -- $99,999,999.99
-- NEVER use FLOAT for money
price FLOAT -- Rounding errors!| 类型 | 范围 | 使用场景 |
|---|---|---|
| TINYINT | -128 到 127 | 年龄、状态码 |
| SMALLINT | -32K 到 32K | 数量 |
| INT | -2.1B 到 2.1B | ID、计数 |
| BIGINT | 极大范围 | 大型ID、时间戳 |
| DECIMAL(p,s) | 精确精度 | 金额 |
| FLOAT/DOUBLE | 近似值 | 科学数据 |
sql
-- 金额必须使用DECIMAL
price DECIMAL(10, 2) -- 最大支持$99,999,999.99
-- 禁止用FLOAT存储金额
price FLOAT -- 会出现舍入误差!Date/Time Types
日期/时间类型
sql
DATE -- 2025-10-31
TIME -- 14:30:00
DATETIME -- 2025-10-31 14:30:00
TIMESTAMP -- Auto timezone conversion
-- Always store in UTC
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPsql
DATE -- 2025-10-31
TIME -- 14:30:00
DATETIME -- 2025-10-31 14:30:00
TIMESTAMP -- 自动时区转换
-- 始终以UTC存储
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPBoolean
布尔类型
sql
-- PostgreSQL
is_active BOOLEAN DEFAULT TRUE
-- MySQL
is_active TINYINT(1) DEFAULT 1sql
-- PostgreSQL
is_active BOOLEAN DEFAULT TRUE
-- MySQL
is_active TINYINT(1) DEFAULT 1When to Create Indexes
何时创建索引
| Always Index | Reason |
|---|---|
| Foreign keys | Speed up JOINs |
| WHERE clause columns | Speed up filtering |
| ORDER BY columns | Speed up sorting |
| Unique constraints | Enforced uniqueness |
sql
-- Foreign key index
CREATE INDEX idx_orders_customer ON orders(customer_id);
-- Query pattern index
CREATE INDEX idx_orders_status_date ON orders(status, created_at);| 需始终添加索引的场景 | 原因 |
|---|---|
| 外键 | 加速关联查询 |
| WHERE子句中的列 | 加速过滤 |
| ORDER BY子句中的列 | 加速排序 |
| 唯一约束 | 强制唯一性 |
sql
-- 外键索引
CREATE INDEX idx_orders_customer ON orders(customer_id);
-- 针对查询模式的索引
CREATE INDEX idx_orders_status_date ON orders(status, created_at);Index Types
索引类型
| Type | Best For | Example |
|---|---|---|
| B-Tree | Ranges, equality | |
| Hash | Exact matches only | |
| Full-text | Text search | |
| Partial | Subset of rows | |
| 类型 | 最佳适用场景 | 示例 |
|---|---|---|
| B-Tree | 范围查询、等值查询 | |
| Hash | 仅精确匹配 | |
| 全文索引 | 文本搜索 | |
| 部分索引 | 行的子集 | |
Composite Index Order
复合索引顺序
sql
CREATE INDEX idx_customer_status ON orders(customer_id, status);
-- Uses index (customer_id first)
SELECT * FROM orders WHERE customer_id = 123;
SELECT * FROM orders WHERE customer_id = 123 AND status = 'pending';
-- Does NOT use index (status alone)
SELECT * FROM orders WHERE status = 'pending';Rule: Most selective column first, or column most queried alone.
sql
CREATE INDEX idx_customer_status ON orders(customer_id, status);
-- 会使用索引(customer_id在前)
SELECT * FROM orders WHERE customer_id = 123;
SELECT * FROM orders WHERE customer_id = 123 AND status = 'pending';
-- 不会使用索引(仅用status)
SELECT * FROM orders WHERE status = 'pending';规则: 选择性最高的列优先,或单独查询最频繁的列优先。
Index Pitfalls
索引陷阱
| Pitfall | Problem | Solution |
|---|---|---|
| Over-indexing | Slow writes | Only index what's queried |
| Wrong column order | Unused index | Match query patterns |
| Missing FK indexes | Slow JOINs | Always index FKs |
| 陷阱 | 问题 | 解决方案 |
|---|---|---|
| 过度索引 | 写入速度变慢 | 只为查询需要的列添加索引 |
| 列顺序错误 | 索引未被使用 | 匹配查询模式 |
| 外键未加索引 | 关联查询缓慢 | 始终为外键添加索引 |
Primary Keys
主键
sql
-- Auto-increment (simple)
id INT AUTO_INCREMENT PRIMARY KEY
-- UUID (distributed systems)
id CHAR(36) PRIMARY KEY DEFAULT (UUID())
-- Composite (junction tables)
PRIMARY KEY (student_id, course_id)sql
-- 自增主键(简单场景)
id INT AUTO_INCREMENT PRIMARY KEY
-- UUID主键(分布式系统)
id CHAR(36) PRIMARY KEY DEFAULT (UUID())
-- 复合主键(关联表)
PRIMARY KEY (student_id, course_id)Foreign Keys
外键
sql
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE CASCADE -- Delete children with parent
ON DELETE RESTRICT -- Prevent deletion if referenced
ON DELETE SET NULL -- Set to NULL when parent deleted
ON UPDATE CASCADE -- Update children when parent changes| Strategy | Use When |
|---|---|
| CASCADE | Dependent data (order_items) |
| RESTRICT | Important references (prevent accidents) |
| SET NULL | Optional relationships |
sql
FOREIGN KEY (customer_id) REFERENCES customers(id)
ON DELETE CASCADE -- 删除父表时同时删除子表数据
ON DELETE RESTRICT -- 存在引用时禁止删除父表数据
ON DELETE SET NULL -- 删除父表时将子表对应列设为NULL
ON UPDATE CASCADE -- 更新父表时同步更新子表数据| 策略 | 使用场景 |
|---|---|
| CASCADE | 依赖数据(如order_items) |
| RESTRICT | 重要引用(防止误删) |
| SET NULL | 可选关系 |
Other Constraints
其他约束
sql
-- Unique
email VARCHAR(255) UNIQUE NOT NULL
-- Composite unique
UNIQUE (student_id, course_id)
-- Check
price DECIMAL(10,2) CHECK (price >= 0)
discount INT CHECK (discount BETWEEN 0 AND 100)
-- Not null
name VARCHAR(100) NOT NULLsql
-- 唯一约束
email VARCHAR(255) UNIQUE NOT NULL
-- 复合唯一约束
UNIQUE (student_id, course_id)
-- 检查约束
price DECIMAL(10,2) CHECK (price >= 0)
discount INT CHECK (discount BETWEEN 0 AND 100)
-- 非空约束
name VARCHAR(100) NOT NULLOne-to-Many
一对多
sql
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(id)
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
product_id INT NOT NULL,
quantity INT NOT NULL
);sql
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(id)
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
product_id INT NOT NULL,
quantity INT NOT NULL
);Many-to-Many
多对多
sql
-- Junction table
CREATE TABLE enrollments (
student_id INT REFERENCES students(id) ON DELETE CASCADE,
course_id INT REFERENCES courses(id) ON DELETE CASCADE,
enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (student_id, course_id)
);sql
-- 关联表
CREATE TABLE enrollments (
student_id INT REFERENCES students(id) ON DELETE CASCADE,
course_id INT REFERENCES courses(id) ON DELETE CASCADE,
enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (student_id, course_id)
);Self-Referencing
自引用
sql
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
manager_id INT REFERENCES employees(id)
);sql
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
manager_id INT REFERENCES employees(id)
);Polymorphic
多态关联
sql
-- Approach 1: Separate FKs (stronger integrity)
CREATE TABLE comments (
id INT PRIMARY KEY,
content TEXT NOT NULL,
post_id INT REFERENCES posts(id),
photo_id INT REFERENCES photos(id),
CHECK (
(post_id IS NOT NULL AND photo_id IS NULL) OR
(post_id IS NULL AND photo_id IS NOT NULL)
)
);
-- Approach 2: Type + ID (flexible, weaker integrity)
CREATE TABLE comments (
id INT PRIMARY KEY,
content TEXT NOT NULL,
commentable_type VARCHAR(50) NOT NULL,
commentable_id INT NOT NULL
);sql
-- 方式1:单独外键(完整性更强)
CREATE TABLE comments (
id INT PRIMARY KEY,
content TEXT NOT NULL,
post_id INT REFERENCES posts(id),
photo_id INT REFERENCES photos(id),
CHECK (
(post_id IS NOT NULL AND photo_id IS NULL) OR
(post_id IS NULL AND photo_id IS NOT NULL)
)
);
-- 方式2:类型+ID(更灵活,完整性较弱)
CREATE TABLE comments (
id INT PRIMARY KEY,
content TEXT NOT NULL,
commentable_type VARCHAR(50) NOT NULL,
commentable_id INT NOT NULL
);Embedding vs Referencing
嵌入 vs 引用
| Factor | Embed | Reference |
|---|---|---|
| Access pattern | Read together | Read separately |
| Relationship | 1:few | 1:many |
| Document size | Small | Approaching 16MB |
| Update frequency | Rarely | Frequently |
| 因素 | 嵌入 | 引用 |
|---|---|---|
| 访问模式 | 一起读取 | 单独读取 |
| 关系 | 一对少 | 一对多 |
| 文档大小 | 小 | 接近16MB |
| 更新频率 | 低 | 高 |
Embedded Document
嵌入文档
json
{
"_id": "order_123",
"customer": {
"id": "cust_456",
"name": "Jane Smith",
"email": "jane@example.com"
},
"items": [
{ "product_id": "prod_789", "quantity": 2, "price": 29.99 }
],
"total": 109.97
}json
{
"_id": "order_123",
"customer": {
"id": "cust_456",
"name": "Jane Smith",
"email": "jane@example.com"
},
"items": [
{ "product_id": "prod_789", "quantity": 2, "price": 29.99 }
],
"total": 109.97
}Referenced Document
引用文档
json
{
"_id": "order_123",
"customer_id": "cust_456",
"item_ids": ["item_1", "item_2"],
"total": 109.97
}json
{
"_id": "order_123",
"customer_id": "cust_456",
"item_ids": ["item_1", "item_2"],
"total": 109.97
}MongoDB Indexes
MongoDB索引
javascript
// Single field
db.users.createIndex({ email: 1 }, { unique: true });
// Composite
db.orders.createIndex({ customer_id: 1, created_at: -1 });
// Text search
db.articles.createIndex({ title: "text", content: "text" });
// Geospatial
db.stores.createIndex({ location: "2dsphere" });javascript
// 单字段索引
db.users.createIndex({ email: 1 }, { unique: true });
// 复合索引
db.orders.createIndex({ customer_id: 1, created_at: -1 });
// 全文索引
db.articles.createIndex({ title: "text", content: "text" });
// 地理空间索引
db.stores.createIndex({ location: "2dsphere" });Migration Best Practices
迁移最佳实践
| Practice | WHY |
|---|---|
| Always reversible | Need to rollback |
| Backward compatible | Zero-downtime deploys |
| Schema before data | Separate concerns |
| Test on staging | Catch issues early |
| 实践 | 原因 |
|---|---|
| 始终支持回滚 | 需要能回滚到之前的状态 |
| 保证向后兼容 | 支持零停机部署 |
| 先改架构再改数据 | 分离关注点 |
| 在staging环境测试 | 提前发现问题 |
Adding a Column (Zero-Downtime)
零停机添加列
sql
-- Step 1: Add nullable column
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- Step 2: Deploy code that writes to new column
-- Step 3: Backfill existing rows
UPDATE users SET phone = '' WHERE phone IS NULL;
-- Step 4: Make required (if needed)
ALTER TABLE users MODIFY phone VARCHAR(20) NOT NULL;sql
-- 步骤1:添加可空列
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- 步骤2:部署写入新列的代码
-- 步骤3:回填现有数据
UPDATE users SET phone = '' WHERE phone IS NULL;
-- 步骤4:设置为必填(如果需要)
ALTER TABLE users MODIFY phone VARCHAR(20) NOT NULL;Renaming a Column (Zero-Downtime)
零停机重命名列
sql
-- Step 1: Add new column
ALTER TABLE users ADD COLUMN email_address VARCHAR(255);
-- Step 2: Copy data
UPDATE users SET email_address = email;
-- Step 3: Deploy code reading from new column
-- Step 4: Deploy code writing to new column
-- Step 5: Drop old column
ALTER TABLE users DROP COLUMN email;sql
-- 步骤1:添加新列
ALTER TABLE users ADD COLUMN email_address VARCHAR(255);
-- 步骤2:复制数据
UPDATE users SET email_address = email;
-- 步骤3:部署读取新列的代码
-- 步骤4:部署写入新列的代码
-- 步骤5:删除旧列
ALTER TABLE users DROP COLUMN email;Migration Template
迁移模板
sql
-- Migration: YYYYMMDDHHMMSS_description.sql
-- UP
BEGIN;
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_users_phone ON users(phone);
COMMIT;
-- DOWN
BEGIN;
DROP INDEX idx_users_phone ON users;
ALTER TABLE users DROP COLUMN phone;
COMMIT;sql
-- 迁移文件:YYYYMMDDHHMMSS_description.sql
-- UP(升级)
BEGIN;
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_users_phone ON users(phone);
COMMIT;
-- DOWN(回滚)
BEGIN;
DROP INDEX idx_users_phone ON users;
ALTER TABLE users DROP COLUMN phone;
COMMIT;Query Analysis
查询分析
sql
EXPLAIN SELECT * FROM orders
WHERE customer_id = 123 AND status = 'pending';| Look For | Meaning |
|---|---|
| type: ALL | Full table scan (bad) |
| type: ref | Index used (good) |
| key: NULL | No index used |
| rows: high | Many rows scanned |
sql
EXPLAIN SELECT * FROM orders
WHERE customer_id = 123 AND status = 'pending';| 需关注的内容 | 含义 |
|---|---|
| type: ALL | 全表扫描(性能差) |
| type: ref | 使用了索引(性能好) |
| key: NULL | 未使用索引 |
| rows: 数值大 | 扫描了大量行 |
N+1 Query Problem
N+1查询问题
python
undefinedpython
undefinedBAD: N+1 queries
错误:N+1次查询
orders = db.query("SELECT * FROM orders")
for order in orders:
customer = db.query(f"SELECT * FROM customers WHERE id = {order.customer_id}")
orders = db.query("SELECT * FROM orders")
for order in orders:
customer = db.query(f"SELECT * FROM customers WHERE id = {order.customer_id}")
GOOD: Single JOIN
正确:单次关联查询
results = db.query("""
SELECT orders.*, customers.name
FROM orders
JOIN customers ON orders.customer_id = customers.id
""")
undefinedresults = db.query("""
SELECT orders.*, customers.name
FROM orders
JOIN customers ON orders.customer_id = customers.id
""")
undefinedOptimization Techniques
优化技巧
| Technique | When to Use |
|---|---|
| Add indexes | Slow WHERE/ORDER BY |
| Denormalize | Expensive JOINs |
| Pagination | Large result sets |
| Caching | Repeated queries |
| Read replicas | Read-heavy load |
| Partitioning | Very large tables |
| 技巧 | 使用场景 |
|---|---|
| 添加索引 | WHERE/ORDER BY查询缓慢 |
| 反规范化 | 关联查询成本高 |
| 分页 | 结果集过大 |
| 缓存 | 查询重复率高 |
| 读副本 | 读密集型负载 |
| 分区 | 表数据量极大 |
Extension Points
扩展方向
- Database-Specific Patterns: Add MySQL vs PostgreSQL vs SQLite variations
- Advanced Patterns: Time-series, event sourcing, CQRS, multi-tenancy
- ORM Integration: TypeORM, Prisma, SQLAlchemy patterns
- Monitoring: Query performance tracking, slow query alerts
- 数据库特定模式: 添加MySQL、PostgreSQL、SQLite的差异实现
- 高级模式: 时间序列、事件溯源、CQRS、多租户
- ORM集成: TypeORM、Prisma、SQLAlchemy的使用模式
- 监控: 查询性能跟踪、慢查询告警