六十五、【Linux数据库】MySQL表结构 、 MySQL键值

表结构设计全景图

设计原则 规范化设计 数据建模 反范式优化 存储引擎选择 表结构设计 索引策略 键值设计 业务需求 字段定义 数据类型选择 约束条件 性能优化

MySQL 表结构与键值功能概述

表结构核心概念

  1. 数据类型:定义列中存储的数据类型(整数、字符串、日期等)
  2. 约束条件:限制列中数据的规则(非空、唯一、默认值等)
  3. 存储引擎:决定表的物理存储方式(InnoDB、MyISAM)
  4. 字符集:指定字符编码(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. 创建表

bash 复制代码
# 登录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. 修改表结构

bash 复制代码
# 添加新列
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. 查看表结构

bash 复制代码
# 查看表定义
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. 主键管理

bash 复制代码
# 创建表时定义主键
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. 外键约束

bash 复制代码
# 添加外键约束
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. 索引管理

bash 复制代码
# 创建普通索引
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. 索引使用分析

bash 复制代码
# 查看索引使用
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. 分区表

bash 复制代码
# 创建范围分区表
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. 生成列

bash 复制代码
# 创建虚拟生成列
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 数据类型

bash 复制代码
# 创建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 添加生成列 生成表达式