MySQL 系统学习 第五阶段:企业级 MySQL 实战开发 第九章:数据库性能优化实战
2026/7/14 10:22:32 网站建设 项目流程

一、为什么数据库会变慢?

很多初学者认为:

数据库慢,就是 MySQL 性能不好。

实际上:

大多数问题来自:

SQL 和表设计不合理。


例如:

用户表:

user

数据:

1000万条

执行:

SELECT * FROM user WHERE username='Tom';

数据库需要:

从第一条扫描到最后。


这个过程:

叫:

全表扫描(Full Table Scan)


二、什么是索引(Index)?

定义:

索引:

一种帮助数据库快速查询数据的数据结构。

类似:

书的目录。


没有索引:

看一本书:

逐页找:

第一页 第二页 第三页 ... 1000页

有索引:

查目录:

直接定位:

第500页

数据库:

没有索引:

逐行扫描

有索引:

快速定位

三、为什么索引能提高查询速度?

例如:

用户表:

100万数据。

字段:

id username

没有索引:

查询:

WHERE username='Tom'

流程:

第1行 ↓ 第2行 ↓ 第3行 ↓ ... 100万行

复杂度:

O(n)


有索引:

索引树 Tom ↓ 数据位置 ↓ 直接读取

接近:

O(log n)


四、MySQL索引结构:B+Tree ⭐⭐⭐⭐⭐

MySQL InnoDB 默认:

B+Tree。


结构:

类似:

50 / \ 20 80 / \ / \ 10 30 60 90

查询:

查:

90

流程:

根节点 ↓ 80 ↓ 90

不需要扫描所有数据。


五、为什么不用二叉树?

普通二叉树:

问题:

数据量大:

高度太高。


例如:

1000万数据:

二叉树:

可能:

几十层。


B+Tree:

一个节点:

保存大量数据。

高度低。


优势:

  • 查询快
  • 范围查询强
  • 适合磁盘读取

六、索引类型

1. 主键索引

例如:

id BIGINT PRIMARY KEY

自动创建。


特点:

唯一。


2. 普通索引

例如:

用户搜索:

username

创建:

CREATE INDEX idx_username ON user(username);

3. 唯一索引

例如:

邮箱:

email UNIQUE

保证:

不能重复。


4. 联合索引

多个字段:

例如:

username status

创建:

CREATE INDEX idx_user_status ON user(username,status);

七、为什么企业需要联合索引?

场景:

后台用户列表:

条件:

WHERE username='Tom' AND status=1

如果只有:

username索引。

查询:

先找到Tom。

再过滤status。


联合索引:

(username,status)

直接定位。


效率更高。


八、最左匹配原则 ⭐⭐⭐⭐⭐

联合索引:

(username,status,age)

有效:

WHERE username='Tom'


有效:

WHERE username='Tom' AND status=1


有效:

WHERE username='Tom' AND status=1 AND age=20


无效:

WHERE status=1


无效:

WHERE age=20


原因:

索引顺序:

从左开始。


九、什么情况下不要创建索引?

索引不是越多越好。


1. 数据量小

例如:

100条数据。

全表扫描更快。


2. 经常修改字段

例如:

状态字段:

status

如果频繁修改:

维护索引成本增加。


3. 区分度低

例如:

性别:

male female

只有两个值。

索引效果差。


十、EXPLAIN 执行计划 ⭐⭐⭐⭐⭐

优化SQL必须使用:

EXPLAIN

例如:

EXPLAIN SELECT * FROM user WHERE username='Tom';

查看:

数据库如何执行。


重点字段:

type

表示查询类型。


最好:

const eq_ref ref

较差:

ALL

表示:

全表扫描。


key

实际使用索引。


例如:

idx_username

说明:

使用索引。


rows

扫描行数。

越少越好。


十一、慢 SQL 分析流程

企业常用:

流程:

发现慢SQL ↓ EXPLAIN ↓ 查看是否走索引 ↓ 优化SQL ↓ 增加索引 ↓ 重新测试

例如:

慢:

SELECT * FROM orders WHERE user_id=100;

检查:

没有索引:

type=ALL

优化:

添加:

INDEX(user_id)

再次:

EXPLAIN:

type=ref

优化成功。


十二、分页优化 ⭐⭐⭐⭐⭐

普通分页:

LIMIT 100000,20

问题:

MySQL:

先扫描:

100000条。

然后丢弃。


数据越大:

越慢。


例如:

第500万页。


优化方案1:ID分页

推荐:

SELECT * FROM user WHERE id>500000 LIMIT 20;

利用:

主键索引。


速度快。


优化方案2:记录最后ID

例如:

第一页:

返回:

lastId=20

第二页:

WHERE id>20

互联网大量使用。


十三、大数据量查询优化

1. 不查询无用字段

不要:

SELECT *

推荐:

SELECT id,name

减少:

网络传输。


2. 避免深层JOIN

例如:

user join order join product join payment

复杂。


拆开查询。


3. 热点数据缓存

例如:

商品详情:

访问频繁。


使用:

Redis。


十四、TypeORM 性能优化

1. 不滥用 relations

错误:

find({ relations:{ orders:true, roles:true, permissions:true } })

可能:

生成巨大JOIN。


推荐:

按需查询。


2. 使用 select

不要:

find()

全部字段。


推荐:

find({ select:{ id:true, username:true } })

3. 分页必须限制

错误:

find()

查询百万数据。


正确:

find({ skip:0, take:20 })

4. 批量操作

错误:

循环:

for(){ save() }

推荐:

批量:

save([ user1, user2, user3 ])

十五、企业索引设计案例

用户表

user

字段:

id username phone status create_time

查询:

后台搜索:

WHERE username AND status

索引:

INDEX(username,status)

十六、订单表优化案例

订单:

orders id user_id status create_time

常见:

查询用户订单:

WHERE user_id=100 ORDER BY create_time DESC

索引:

INDEX( user_id, create_time )

原因:

同时满足:

查询 + 排序。


十七、数据库优化原则总结

SQL层面

✅ 不使用SELECT *

✅ 避免全表扫描

✅ 合理分页

✅ 避免复杂JOIN


表设计

✅ 合理字段类型

✅ 合理索引

✅ 避免冗余数据


TypeORM

✅ 控制查询字段

✅ 合理分页

✅ 不滥用relations

✅ 批量操作


十八、本章总结表

知识作用
索引提高查询速度
B+TreeMySQL索引结构
联合索引优化多条件查询
最左匹配决定索引是否生效
EXPLAIN分析SQL
慢SQL定位性能问题
ID分页解决深分页
select减少数据量
relations避免巨大JOIN

本章一句话总结:

数据库性能优化的核心不是让数据库更快,而是让数据库少做无用工作。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询