表结构设计全景图
设计原则 规范化设计 数据建模 反范式优化 存储引擎选择 表结构设计 索引策略 键值设计 业务需求 字段定义 数据类型选择 约束条件 性能优化
MySQL 表结构与键值功能概述
表结构核心概念
- 数据类型:定义列中存储的数据类型(整数、字符串、日期等)
- 约束条件:限制列中数据的规则(非空、唯一、默认值等)
- 存储引擎:决定表的物理存储方式(InnoDB、MyISAM)
- 字符集:指定字符编码(utf8mb4 支持全 Unicode)
键值类型与作用
| 键类型 |
功能描述 |
特点 |
| 主键 |
唯一标识行 |
非空、唯一、自动创建聚集索引 |
| 外键 |
关联表数据 |
强制引用完整性 |
| 唯一键 |
保证列值唯一 |
允许空值 |
| 普通索引 |
加速查询 |
可多列组合 |
| 全文索引 |
文本搜索优化 |
支持 MATCH AGAINST 操作 |
| 空间索引 |
地理数据查询 |
用于 GIS 数据类型 |
表设计原则对比
| 设计原则 |
规范化设计 |
反范式设计 |
混合设计 |
最佳适用场景 |
| 核心理念 |
消除冗余 |
适当冗余 |
平衡冗余与性能 |
按业务需求选择 |
| 范式级别 |
3NF+ |
1NF-2NF |
2NF-3NF |
OLTP:3NF OLAP:反范式 |
| 表数量 |
多表关联 |
宽表 |
中等 |
高事务:多表 报表:宽表 |
| 查询性能 |
中等 |
高 |
高 |
复杂查询:反范式 |
| 更新性能 |
高 |
低 |
中等 |
频繁更新:规范化 |
| 数据一致性 |
强 |
弱 |
中等 |
关键业务:规范化 |
| 典型应用 |
交易系统 |
数据仓库 |
混合业务 |
按业务类型选择 |
键值类型对比
| 键类型 |
主键(PK) |
外键(FK) |
唯一键(UK) |
索引(Index) |
全文索引(FULLTEXT) |
| 唯一性 |
强制唯一 |
不要求唯一 |
强制唯一 |
不要求唯一 |
不要求唯一 |
| 空值 |
不允许 |
允许 |
允许 |
允许 |
允许 |
| 数量限制 |
每表1个 |
无限制 |
无限制 |
无限制 |
无限制 |
| 创建方式 |
PRIMARY KEY |
FOREIGN KEY |
UNIQUE KEY |
INDEX |
FULLTEXT INDEX |
| 主要作用 |
行标识 |
引用完整性 |
业务唯一性 |
查询加速 |
文本搜索 |
| 物理结构 |
聚集索引 |
二级索引 |
二级索引 |
二级索引 |
倒排索引 |
| 性能影响 |
高 |
中 |
中 |
中 |
高(写入) |
一、表结构操作演示
1. 创建表
# 登录MySQL
[root@localhost ~]# mysql -u root -p
Enter password: ******
# 创建数据库
mysql> CREATE DATABASE company CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 创建员工表
mysql> USE company;
mysql> CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
hire_date DATE NOT NULL,
salary DECIMAL(10,2) DEFAULT 0.00,
department_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_name (first_name, last_name),
FULLTEXT INDEX idx_email (email)
) ENGINE=InnoDB;
2. 修改表结构
# 添加新列
mysql> ALTER TABLE employees ADD COLUMN phone VARCHAR(20) AFTER email;
# 修改列类型
mysql> ALTER TABLE employees MODIFY salary DECIMAL(12,2);
# 删除列
mysql> ALTER TABLE employees DROP COLUMN created_at;
# 重命名表
mysql> RENAME TABLE employees TO staff;
3. 查看表结构
# 查看表定义
mysql> SHOW CREATE TABLE staff\G
*************************** 1. row ***************************
Table: staff
Create Table: CREATE TABLE `staff` (
`id` int NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`phone` varchar(20) DEFAULT NULL,
`hire_date` date NOT NULL,
`salary` decimal(12,2) DEFAULT '0.00',
`department_id` int DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
KEY `idx_name` (`first_name`,`last_name`),
FULLTEXT KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
# 查看表信息
mysql> DESCRIBE staff;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| first_name | varchar(50) | NO | MUL | NULL | |
| last_name | varchar(50) | NO | | NULL | |
| email | varchar(100) | YES | UNI | NULL | |
| phone | varchar(20) | YES | | NULL | |
| hire_date | date | NO | | NULL | |
| salary | decimal(12,2)| YES | | 0.00 | |
| department_id | int | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
二、键值操作演示
1. 主键管理
# 创建表时定义主键
mysql> CREATE TABLE departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(100) NOT NULL
);
# 添加主键
mysql> ALTER TABLE staff ADD PRIMARY KEY (id);
# 删除主键
mysql> ALTER TABLE staff DROP PRIMARY KEY;
2. 外键约束
# 添加外键约束
mysql> ALTER TABLE staff ADD CONSTRAINT fk_dept
FOREIGN KEY (department_id) REFERENCES departments(dept_id)
ON DELETE SET NULL ON UPDATE CASCADE;
# 查看外键
mysql> SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'departments';
3. 索引管理
# 创建普通索引
mysql> CREATE INDEX idx_hire_date ON staff(hire_date);
# 创建唯一索引
mysql> CREATE UNIQUE INDEX uniq_email ON staff(email);
# 创建全文索引
mysql> CREATE FULLTEXT INDEX ft_idx_name ON staff(first_name, last_name);
# 删除索引
mysql> DROP INDEX idx_hire_date ON staff;
4. 索引使用分析
# 查看索引使用
mysql> EXPLAIN SELECT * FROM staff WHERE last_name = 'Smith';
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | staff| NULL | ref | idx_name | idx_name | 152 | const | 1 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
# 强制使用索引
mysql> SELECT * FROM staff FORCE INDEX (idx_name) WHERE first_name = 'John';
索引设计矩阵
| 索引类型 |
单列索引 |
复合索引 |
覆盖索引 |
前缀索引 |
最佳实践 |
| 创建语法 |
INDEX (col) |
INDEX (col1,col2) |
包含所有查询列 |
INDEX (col(10)) |
按查询模式设计 |
| 适用场景 |
等值查询 |
范围查询+排序 |
只读查询 |
长文本字段 |
组合查询:复合索引 |
| 索引大小 |
小 |
中等 |
大 |
小 |
空间敏感:前缀索引 |
| 查询速度 |
快 |
快 |
最快 |
中等 |
性能优先:覆盖索引 |
| 更新代价 |
低 |
中 |
高 |
低 |
写密集:单列索引 |
| 使用限制 |
无 |
最左前缀原则 |
列数限制 |
部分匹配 |
遵循最左前缀原则 |
三、高级表结构操作
1. 分区表
# 创建范围分区表
mysql> CREATE TABLE sales (
id INT AUTO_INCREMENT,
sale_date DATE NOT NULL,
amount DECIMAL(10,2),
PRIMARY KEY (id, sale_date)
) PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN MAXVALUE
);
# 添加分区
mysql> ALTER TABLE sales ADD PARTITION (
PARTITION p2024 VALUES LESS THAN (2025)
);
2. 生成列
# 创建虚拟生成列
mysql> ALTER TABLE staff ADD full_name VARCHAR(100)
GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name)) VIRTUAL;
# 查询使用
mysql> SELECT full_name FROM staff WHERE id = 1;
+-----------------+
| full_name |
+-----------------+
| John Smith |
+-----------------+
3. JSON 数据类型
# 创建JSON列
mysql> ALTER TABLE staff ADD profile JSON;
# 插入JSON数据
mysql> UPDATE staff SET profile = '{"skills": ["MySQL", "PHP"], "experience": 5}' WHERE id = 1;
# 查询JSON字段
mysql> SELECT profile->"$.skills[0]" AS primary_skill FROM staff;
+---------------+
| primary_skill |
+---------------+
| "MySQL" |
+---------------+
命令总结表格
| 演示命令 |
功能描述 |
关键参数 |
CREATE TABLE t (id INT PRIMARY KEY) |
创建表 |
列定义、键值 |
ALTER TABLE t ADD COLUMN c VARCHAR(50) |
添加列 |
列名和类型 |
ALTER TABLE t ADD PRIMARY KEY (id) |
添加主键 |
主键列 |
ALTER TABLE t ADD CONSTRAINT fk FOREIGN KEY (c) REFERENCES t2(c2) |
添加外键 |
约束名、关联表 |
CREATE INDEX idx ON t(c) |
创建索引 |
索引名、列 |
DROP INDEX idx ON t |
删除索引 |
索引名 |
SHOW CREATE TABLE t\G |
查看表结构 |
\G 格式化输出 |
EXPLAIN SELECT ... |
分析查询 |
查看索引使用 |
ALTER TABLE t PARTITION BY RANGE (c) (...) |
创建分区 |
分区类型和规则 |
ALTER TABLE t ADD COLUMN c GENERATED ALWAYS AS (expr) VIRTUAL |
添加生成列 |
生成表达式 |