在应用的的开发过程中,由于初期数据量小,开发人员写 SQL 语句时更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,很多 SQL 语句开始逐渐显露出性能问题,对生产的影响也越来越大,此时这些有问题的 SQL 语句就成为整个系统性能的瓶颈,因此我们必须要对它们进行优化。
-
可以使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看 SQL 的执行情况,定位低效率sql,同时对一些锁表操作进行优化。
-
然后再用explain分析执行计划:通过该命令可以查看SQL在真正执行时所需要经历的一系列过程,通过执行结果可以看出一条复杂的SQL查找顺序、是否有通过索引查询等信息。执行计划命令所带的SQL并不会真正执行,所以不会担心占用系统资源,用于对SQL进行分析优化非常有用。。(是否索引失效,用到索引没,用了哪些)
mysql> select * from post;
+----+------------------+--------+---------------+-------------------+--------------+--------+---------------------+---------------------+
| id | post_id | title | content | author_id | community_id | status | create_time | update_time |
+----+------------------+--------+---------------+-------------------+--------------+--------+---------------------+---------------------+
| 1 | 959630985400320 | 真牛逼 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-03 23:33:13 | 2022-07-03 23:33:13 |
| 2 | 1127631193903104 | 你好 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-04 10:40:48 | 2022-07-04 10:40:48 |
| 3 | 1149343172136960 | 你好 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-04 12:07:04 | 2022-07-04 12:07:04 |
| 4 | 1149745036791808 | 你好 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-04 12:08:40 | 2022-07-04 12:08:40 |
| 5 | 1149992383287296 | 你好 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-04 12:09:39 | 2022-07-04 12:09:39 |
| 6 | 1153257435041792 | 111 | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-04 12:22:38 | 2022-07-04 12:22:38 |
| 7 | 1643974875942912 | 投票 | 1111112222222 | -4552349083234304 | 1 | 1 | 2022-07-05 20:52:34 | 2022-07-05 20:52:34 |
| 8 | 1644037979246592 | lllk | 1111112222222 | -4552349083234304 | 1 | 1 | 2022-07-05 20:52:49 | 2022-07-05 20:52:49 |
| 9 | 1644081310601216 | qqqql | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-05 20:52:59 | 2022-07-05 20:52:59 |
| 10 | 1644113220866048 | hello | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-05 20:53:07 | 2022-07-05 20:53:07 |
| 11 | 8813050287099904 | hello | 1111112222222 | -4552349083234304 | 2 | 1 | 2022-07-25 15:39:54 | 2022-07-25 15:39:54 |
+----+------------------+--------+---------------+-------------------+--------------+--------+---------------------+---------------------+
11 rows in set (0.00 sec)
mysql> show processlist;
+----+------+-----------------+----------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------------+----------+---------+------+----------+------------------+
| 6 | root | localhost:63386 | bluebell | Query | 0 | starting | show processlist |
+----+------+-----------------+----------+---------+------+----------+------------------+
1 row in set (0.00 sec)
mysql> explain select * from user;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | user | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
type:表示MySQL在表中找到所需行的方式,或者叫访问类型
- type=ALL,全表扫描,MySQL遍历全表来找到匹配行
- type=index,索引全扫描
- type=range,索引范围扫描
- type=eq_ref,唯一索引
- type=NULL,MySQL不用访问表或者索引,直接就能够得到结果(性能最好)
possible_keys: 表示查询可能使用的索引
key: 实际使用的索引
key_len: 使用索引字段的长度
rows: 扫描行的数量
Extra:
- using index:覆盖索引,不回表
- using where:回表查询
- using filesort:需要额外的排序,不能通过索引得到排序结果
优化
如果大多数时间都正常,偶尔很慢,那可能是,数据库在刷新脏页,例如 log redo写满了,需要同步到磁盘。或者执行的时候遇到了锁,或者本次sql写的不对。如果一直执行很慢,那有可能是没用索引,或者索引失效。这时我们需要结合具体的手段去定位慢sql。