MySQL 慢查询优化

1,060 阅读3分钟

前言

优化一个 Web 项目的方法还有很多,比如合理的在后端给返回数据加缓存、充分利用浏览器的前端缓存、CDN,实在不行甚至需要「劳师动众」的部署多台机器做集群和负载均衡等等。该博客将放在数据库慢查询的优化上,这个话题对于 Web 项目而言更具有普适的意义。

一方面它不局限于任何一种技术栈,另一方面它更是直接在业务逻辑层面从代码本质上来优化你的项目性能,这往往也是单实例服务下性能的瓶颈所在。

一个起步就不简单的原因是,我们如何才能定位到那些真正形成瓶颈的慢查询。一个普通项目中的 SQL 可能就有大几十甚至上百个,而「凶手们」就藏匿其中。

一个朴素的想法是在项目中每一个 SQL 执行前后打上时间戳来估计执行时间,暂且不论由于各种因素的影响这种估算可能不准确,更让人不可接受的是这对原始代码造成的极大的侵入。

检查慢日志是否开启

SHOW VARIABLES LIKE '%slow%';

image.png

开启慢查询日志

方法一:

修改配置文件  在 my.ini 增加几行:  主要是慢查询的定义时间(超过2秒就是慢查询),以及慢查询log日志记录( slow_query_log)

[mysqld]
//其他配置项
slow_query_log=1
slow_query_log_file=/var/log/mysql/log-slow-queries.log
long_query_time=2

image.png

方法二:

通过MySQL数据库开启慢查询:

//开启慢日志
mysql> set global slow_query_log=on;
Query OK, 0 rows affected (0.08 sec)

//设置慢查询时间阈值
mysql> set global long_query_time=3600;
Query OK, 0 rows affected (0.08 sec)

//设置控制是否记录未走索引的 SQL 查询
mysql> set global log_queries_not_using_indexes=on;
Query OK, 0 rows affected (0.00 sec)

image.png

测试SQL

小伙伴可参考 MySQL生成百万级测试数据

执行SQL,超过阈值则记录慢日志中

image.png

检查对应慢日志

image.png

使用Explain工具对慢SQL进行分析

Explain参数详情可参考 explain参数详解

执行后参数分析

explain select * from users;

image.png

SQL优化分析

SQL优化可参考 MySQL 常用SQL语句优化

  1. select * form users;

从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。

所以,你应该养成一个需要什么就取什么的好的习惯。

以上SQL可优化成:

//需要什么就取什么
select id,username form users;//优化后

image.png

  1. select id,username from users where username like "%test%";

索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。

例如,当你需要在一篇大的文章中搜索一个词时,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是没有意义的。你可能需要使用MySQL全文索引或是自己做一个索引(比如说:搜索关键词或是Tag什么的)

image.png

以上SQL加索引后:

ALTER TABLE `users` ADD INDEX index_name ( `username` );

image.png

以上SQL优化后:

//like 优化 去掉前面的%   例:like "%test%" => like "test%";
select username from users where username like "test%";;//优化后

image.png