mysql 查询速度提升 10000+ 倍,竟是如此的简单

参考文章:

MYSQL性能调优(二)EXPLAIN/DESC

MYSQL性能调优(一)慢查询日志

一、问题

你见过一个联表查询需要3300+秒么?今天我们的慢查询日志捕捉到了一只,我们一起来解剖一下看看这到底是何方妖孽。

二、分析优化

1、首先,我们查看一下罪魁祸首的执行计划

EXPLAIN
SELECT 
        r.id
        ,si.set_id
        ,m.project_id 应添加项目列表
FROM report r 
        INNER JOIN application a ON r.app_id=a.id
        INNER JOIN application_sample s ON a.id=s.app_id
        INNER JOIN application_sample_item si ON s.id=si.sample_id                            
        INNER JOIN set_project_mapping m ON si.set_id=m.set_id
WHERE r.org_id =54 AND r.report_status=2 AND r.del=0 AND r.barcode <> '' 
        AND r.add_date BETWEEN '2020-11-01' AND '2020-11-02' 
        AND a.del=0 AND a.application_status=4;

从执行计划我们可以发现,有两张表 m和si 使用的是全表扫描,并且根据执行计划估算的这两张表需要扫描的行数看,按照笛卡儿积交叉,扫描数量级一下就到了6000万+,再与其他表关联,结果就是爆炸

2、到这里,我们基本可以确定问题出在两张表的全表扫瞄上了

所以,我们尝试优化这两张表,为两张表的关联字段添加索引

ALTER TABLE `set_project_mapping` ADD INDEX set_id( `set_id` ) ;
ALTER TABLE `application_sample_item` ADD INDEX index_sample( `sample_id` ) ;

然后,重新执行查询,看看有改善

查询时间从3000+秒提升到了2.829s,效果还是很显著的

3、但是,按照产品要求以及慢查询设置,超过2s依然为慢查询,需要继续优化

再看执行计划

从执行计划,我们可以发现之前s表的主键索引失效了,为什么主键索引会失效呢?

仔细对比两份计划,我们可以初步发现两者的执行顺序不同了,之前是先执行si表,然后通过si表sample_id直接查s表的主键索引id;现在,变成了先查s表从而导致主键索引失效

我们可以用 SHOW WARNINGS; 查看mysql优化器优化后的sql语句

我们可以惊奇的发现,优化后的sql 关联表字段变了,与我们写的sql不一致,查询s表时直接关联到了r表,实际使用的是app_id

因此,我们为 application_sample 的app_id再加一个普通索引

ALTER TABLE `application_sample` ADD INDEX index_app( `app_id` ) ;

同时,我们按照优化器优化sql调整下我们的sql

SELECT 
        r.id
        ,si.set_id
        ,m.project_id 应添加项目列表
FROM report r 
        INNER JOIN application a ON r.app_id=a.id
        INNER JOIN application_sample s ON r.app_id=s.app_id
        INNER JOIN application_sample_item si ON si.sample_id=s.id                            
        INNER JOIN set_project_mapping m ON si.set_id=m.set_id
WHERE r.org_id =54 AND r.report_status=2 AND r.del=0 AND r.barcode <> '' 
        AND r.add_date BETWEEN '2020-11-01' AND '2020-11-02' 
        AND a.del=0 AND a.application_status=4
;

4、再看执行计划,使用了ref普通索引

执行查询,执行时间 0.203s

到这里,我们的目标达成,查询速度从3000+s提高到了0.2s左右

这里的10000倍虽然有些夸张,毕竟是基数太大,但是也不难看出,适当的索引对性能提升还是巨大的

猜你喜欢

转载自blog.csdn.net/kk_gods/article/details/112276809