MySQL 多表查询与体系结构(精简版)

第一部分:多表查询

一、表与表之间的关系

关系类型说明示例
一对一表A一条记录对应表B一条记录用户表 ↔ 用户详情表(通过 user_id 关联)
一对多表A一条记录对应表B多条记录分类表 → 产品表(一个分类有多个产品)
多对多表A多条记录对应表B多条记录用户表 ↔ 权限表(需中间表连接)

二、准备数据

-- 创建数据库并切换
create database db_itheima;
use db_itheima;

-- 创建班级表
drop table if exists classes;
create table classes(cls_id int, cls_name varchar(20));
insert into classes values (1, 'UI'), (2, 'Java'), (3, 'Python'), (4, 'Shell');

-- 创建学生表
drop table if exists students;
create table students(id int, name varchar(20), age int, gender enum('male', 'female'), score decimal(11,2), cls_id int);
insert into students values
    (1, '刘备', 18, 'male', 100.00, 2),
    (2, '貂蝉', 18, 'female', 99.00, 1),
    (3, '赵云', 18, 'male', 98.00, 3),
    (4, '关羽', 18, 'male', 96.00, 3),
    (5, '大乔', 18, 'female', 97.00, 1),
    (6, '小乔', 18, 'female', 97.00, 5);  -- cls_id=5 不存在

三、内连接(INNER JOIN)

说明:返回两表中满足条件的交集记录,不匹配的行不会出现。

语法

select 字段 from 表A inner join 表B on 关联条件;
-- inner 可省略:select 字段 from 表A join 表B on 关联条件;

案例1:查询学生及其班级

-- 内连接:查询学生和班级信息
select * from students inner join classes on students.cls_id = classes.cls_id;

-- 给表起别名
select stu.*,cls.cls_name from students as stu inner join classes as cls on stu.cls_id = cls.cls_id;
idnameagegenderscorecls_idcls_idcls_name
1刘备18male100.0022Java
2貂蝉18female99.0011UI
3赵云18male98.0033Python
4关羽18male96.0033Python
5大乔18female97.0011UI
小乔(cls_id=5)不匹配,不会出现。

案例2:指定字段 + WHERE 条件

-- 查询分数>=97的学生姓名、分数和班级
select stu.id,stu.name,stu.score,cls.cls_name from students as stu inner join classes as cls
on stu.cls_id = cls.cls_id
where stu.score>=97;
idnamescorecls_name
1刘备100.00Java
2貂蝉99.00UI
3赵云98.00Python
5大乔97.00UI

四、左外连接(LEFT JOIN)

说明:以左表为基准,左表数据全部显示,右表无匹配时用 NULL 填充。

语法

select 字段 from 左表 left join 右表 on 关联条件;

案例:查询所有班级及其学生

-- 左外连接:所有班级都要显示,没有学生的班级学生信息为NULL
select stu.id,stu.name,stu.score,cls.cls_name from classes as cls left join students as stu
on stu.cls_id = cls.cls_id;
idnamescorecls_name
5大乔97.00UI
2貂蝉99.00UI
1刘备100.00Java
4关羽96.00Python
3赵云98.00Python
NULLNULLNULLShell
Shell班没有学生,但左连接保证左表(classes)全部显示。

五、右外连接(RIGHT JOIN)

说明:以右表为基准,右表数据全部显示,左表无匹配时用 NULL 填充。

语法

select 字段 from 左表 right join 右表 on 关联条件;

案例:查询所有学生及其班级

-- 右外连接:所有学生都要显示,没有匹配班级的显示NULL
select stu.id,stu.name,stu.score,cls.cls_name from classes as cls right join students as stu
on stu.cls_id = cls.cls_id;
idnamescorecls_name
1刘备100.00Java
2貂蝉99.00UI
3赵云98.00Python
4关羽96.00Python
5大乔97.00UI
6小乔97.00NULL
小乔的cls_id=5没有对应班级,右连接保证右表(students)全部显示。

六、子查询(扩展)

说明:在一个 SELECT 语句中嵌套另一个 SELECT 语句,子查询可出现在 WHERE、FROM、SELECT 位置。

案例1:WHERE 中的子查询

-- 子查询:查询数学成绩大于平均分的学生
select * from tb_score where math > (select avg(math) from tb_score);

执行过程:子查询先算出平均分 84.6,主查询再过滤 math > 84.6 的记录。

idnamemathenglish
1刘备9085
4赵云9588
5貂蝉8892

案例2:SELECT 列表中的子查询

-- 子查询:查询每人成绩及全班最高分
select name,math,(select max(math) from tb_score) as max_math from tb_score;
namemathmax_math
刘备9095
关羽8095
张飞7095
赵云9595
貂蝉8895

七、连接查询对比表

特性内连接 (INNER JOIN)左外连接 (LEFT JOIN)右外连接 (RIGHT JOIN)
关键字inner join / joinleft joinright join
结果集两表交集左表全部 + 右表匹配右表全部 + 左表匹配
NULL 填充不填充右表无匹配填 NULL左表无匹配填 NULL
语法on 关联条件on 关联条件on 关联条件
使用场景查共有数据左表全量展示右表全量展示

第二部分:MySQL 体系结构

一、MySQL四层架构简介

层级名称主要功能
第一层连接层管理连接、身份认证、连接池
第二层服务层SQL解析、优化、缓存
第三层引擎层数据存储和提取的实现
第四层存储层与操作系统交互,数据持久化

二、连接层核心参数

参数说明默认值建议值
max_connections最大连接数151根据业务调整(100-1000)
wait_timeout连接闲置等待时间(秒)28800600-1800
thread_cache_size线程缓存池大小9CPU核心数×2

进程与线程区别

概念特点适用场景
进程资源分配基本单位,资源开销大,数据不共享CPU密集型
线程CPU调度最小单位,依赖进程,资源共享IO密集型

三、存储引擎

什么是存储引擎?

查看存储引擎

-- 查看支持的存储引擎种类
show engines;

-- 查看默认存储引擎
select @@default_storage_engine;
-- 结果:InnoDB

四、MyISAM vs InnoDB对比表

特性MyISAMInnoDB
事务支持不支持支持(ACID特性)
外键支持不支持支持
锁机制表级锁行级锁
适用场景读多写少高并发写操作
崩溃恢复数据损坏风险高自动恢复,双写机制
存储结构每表3个文件(.sdi/.MYI/.MYD)每表1个.ibd文件
性能查询性能较好写操作性能较高

五、事务处理核心语法

-- 开启事务
start transaction;

-- 执行SQL操作(如转账)
update bank set money=money-1000 where name='itwu';
update bank set money=money+1000 where name='我';

-- 提交事务(操作全部成功时)
commit;

-- 回滚事务(操作失败时)
rollback;

重要提示:创建表时引擎必须为InnoDB

六、存储层文件结构

MyISAM文件结构

文件说明
*.sdi表的元数据(MySQL 8.0)
*.MYI索引文件
*.MYD数据文件

InnoDB文件结构

文件说明
.ibd每表独立文件,存储数据和索引
ibdata1全局表空间、数据字典和事务日志
ib_logfile0/1重做日志文件

第三部分:慢查询日志与索引优化

一、慢查询日志配置

/etc/my.cnf 中配置:

[mysqld]
slow_query_log=1                          -- 开启慢查询日志
long_query_time=1                         -- 超过1秒的查询被记录
slow_query_log_file=/var/log/mysql/slow.log  -- 日志文件路径
log_queries_not_using_indexes=1           -- 记录未使用索引的查询

注意事项:

日志内容示例

# Query_time: 0.419292  Lock_time: 0.000002  Rows_sent: 655360  Rows_examined: 655360
select * from user2;
字段含义
Query_time查询耗时(秒)
Lock_time锁等待时间
Rows_sent返回行数
Rows_examined扫描行数(越少越好)

二、EXPLAIN 执行计划

EXPLAIN SELECT * FROM orders WHERE user_id = 123;  -- 分析查询执行计划

核心字段说明

字段说明重要程度
type连接类型,反映查询效率最重要
key实际使用的索引(NULL=没用索引)很重要
rows估算扫描行数(越少越好)很重要
possible_keys可能使用的索引重要
Extra额外信息重要

type 效率对比表(从高到低)

type速度说明
const最快主键/唯一索引等值查询
ref普通索引等值查询
range较快索引范围查询(BETWEEN、>、<)
index较慢全扫描索引树
ALL最慢全表扫描(必须优化!)

三、索引类型简介

索引类型命令特点
主键索引PRIMARY KEY唯一且不为NULL
唯一索引UNIQUE INDEX值不重复,允许NULL
普通索引INDEX允许重复值
联合索引INDEX(col1, col2)多字段组合,遵循最左前缀原则

索引管理命令

-- 查看索引
SHOW INDEX FROM 表名;

-- 添加唯一索引
ALTER TABLE 表名 ADD UNIQUE uk_name (name);

-- 添加普通索引
ALTER TABLE 表名 ADD INDEX idx_name (name);

-- 添加联合索引
ALTER TABLE 表名 ADD INDEX idx_name_age (name, age);

-- 删除索引
DROP INDEX 索引名 ON 表名;

四、加索引前后对比案例

未加索引

EXPLAIN SELECT * FROM tb_people WHERE id = 1990000;
+----+------+------+------+---------+----------+-------------+
| id | type | key  | rows | filtered | Extra                  |
+----+------+------+------+---------+----------+-------------+
|  1 | ALL  | NULL | 2M   | 100.00  | Using where |
+----+------+------+------+---------+----------+-------------+

添加主键索引

ALTER TABLE tb_people ADD PRIMARY KEY(id);

加索引后

EXPLAIN SELECT * FROM tb_people WHERE id = 1990000;
+----+-------+---------+------+----------+-------+
| id | type  | key     | rows | filtered | Extra |
+----+-------+---------+------+----------+-------+
|  1 | const | PRIMARY |    1 | 100.00  |       |
+----+-------+---------+------+----------+-------+

对比: type 从 ALL → const,rows 从 200万 → 1,性能提升约 200 万倍。

知识点速记

1. 表关系:一对一、一对多、多对多 2. 三种连接:内连接(交集)、左连接(左表全)、右连接(右表全) 3. 四层架构:连接层 → 服务层 → 引擎层 → 存储层 4. 两大引擎:MyISAM(读多写少)vs InnoDB(高并发,推荐使用) 5. 事务三操作:start transaction、commit、rollback 6. 索引类型:主键索引、唯一索引、普通索引、联合索引 7. EXPLAIN核心字段:type、key、rows

全文完