数据库查询(数据库查询太慢怎么办?)

数据库查询(数据库查询太慢怎么办?)
数据库查询太慢怎么办?

用户反馈页面加载慢,一查发现是数据库查询拖后腿。这种情况太常见了。

今天聊聊怎么定位和优化MySQL慢查询,不讲太深的理论,就说实用的。

怎么发现慢查询?

首先得知道哪些SQL慢。MySQL有个慢查询日志功能,开启后会自动记录执行时间超过阈值的SQL。

查看当前配置:

SHOW VARIABLES LIKE 'slow_query_log';SHOW VARIABLES LIKE 'long_query_time';

临时开启:

SET GLOBAL slow_query_log = 'ON';SET GLOBAL long_query_time = 1;  -- 超过1秒就记录

开启后,执行慢的SQL都会被记录到日志文件里。

找到慢SQL后怎么分析?

用EXPLAIN命令,它能告诉你这条SQL是怎么执行的。

EXPLAIN SELECT * FROM orders WHERE user_id = 123;

执行后会显示一堆信息,重点看这几个:

type字段 - 访问类型,越往左越好

system > const > eq_ref > ref > range > index > ALL

如果看到ALL,说明在全表扫描,这是最慢的,需要优化。

key字段 - 实际用的索引

如果是NULL,说明没用上索引,这通常就是慢的原因。

rows字段 - 预估扫描行数

这个数字越大,查询越慢。

最常见的优化方法

1. 加索引

90%的慢查询都是因为没索引。

-- 给user_id加索引ALTER TABLE orders ADD INDEX idx_user_id (user_id);

加完后再EXPLAIN看看,type应该从ALL变成ref或range了。

**2. 避免SELECT ***

-- 差:查所有字段SELECT * FROM users WHERE id = 1;-- 好:只查需要的SELECT id, name, email FROM users WHERE id = 1;

字段少了,传输数据量小,自然快。

3. 注意索引失效的情况

有些写法会导致索引用不上:

-- 对字段用函数,索引失效SELECT * FROM users WHERE YEAR(created_at) = 2024;-- 正确写法SELECT * FROM users WHERE created_at >= '2024-01-01';
-- LIKE以%开头,索引失效SELECT * FROM users WHERE name LIKE '%张';-- 这样可以用索引SELECT * FROM users WHERE name LIKE '张%';
-- 类型不匹配,索引失效SELECT * FROM users WHERE phone = 13800138000;  -- phone是varchar-- 正确写法SELECT * FROM users WHERE phone = '13800138000';

4. 分页优化

深分页特别慢:

-- 慢:需要扫描前100万条SELECT * FROM logs ORDER BY id LIMIT 1000000, 20;-- 快:用ID定位SELECT * FROM logs WHERE id > 1000000 ORDER BY id LIMIT 20;

联合索引的坑

假设建了一个联合索引 (a, b, c),使用时要注意顺序:

-- 用得上索引SELECT * FROM t WHERE a = 1;SELECT * FROM t WHERE a = 1 AND b = 2;SELECT * FROM t WHERE a = 1 AND b = 2 AND c = 3;-- 用不上索引!SELECT * FROM t WHERE b = 2;  -- 没有aSELECT * FROM t WHERE b = 2 AND c = 3;  -- 没有a

记住"最左前缀"原则:必须从最左边的字段开始用。

实战案例

问题SQL:

SELECT * FROM orders WHERE status = 'pending' ORDER BY create_time DESC;-- 执行时间:5秒

分析:

EXPLAIN SELECT * FROM orders WHERE status = 'pending' ORDER BY create_time DESC;-- type: ALL(全表扫描)-- Extra: Using filesort(额外排序)

优化:加联合索引

ALTER TABLE orders ADD INDEX idx_status_time (status, create_time);

效果:

-- type: ref-- Extra: Using index condition-- 执行时间:0.05秒

从5秒优化到0.05秒,快了100倍。

几个实用技巧

1. 定期查看慢查询

-- 查看正在执行的SQLSHOW PROCESSLIST;-- 杀掉太慢的查询KILL 查询ID;

2. 查看表索引

数据库查询(数据库查询太慢怎么办?)

SHOW INDEX FROM 表名;

3. 分析表统计信息

ANALYZE TABLE 表名;

小结

MySQL优化核心思路:

  1. 开启慢查询日志,找到慢SQL
  2. 用EXPLAIN分析执行计划
  3. 根据情况加索引、改写法
  4. 验证优化效果

大部分性能问题都是索引问题,先把索引搞明白,能解决80%的慢查询。

顺便说一下,我经常需要远程连公司的测试数据库分析慢查询。以前用公司VPN老是断,后来用星空组网把笔记本和公司网络连起来,在家也能直接连内网的MySQL,EXPLAIN调试方便多了。

有问题欢迎交流~

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有