MySQL慢查询优化实践小结

Posted 一步一步往上爬的小蜗牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL慢查询优化实践小结相关的知识,希望对你有一定的参考价值。

        前不久在跟同事交流慢查询优化的技巧时,遇到一些分歧,上网查阅资料后,纠正了我一些错误的认识,现在记录一下。

疑问点1

        MySQL数据库查询记录时每次是否只能使用一个索引?什么情况下能使用两个索引呢?

        mysql5.0之前,一个表每次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但从5.1开始,引入了 index merge 优化技术,对同一个表查询可以使用多个索引分别进行条件扫描。

        where 中可能有多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术。index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)

        根据查到的资料和例子,我创建test表来进行验证

CREATE TABLE test ( 
    id BIGINT(20) NOT NULL AUTO_INCREMENT, 
    start_time DATETIME NOT NULL COMMENT '开始时间', 
    end_time DATETIME NOT NULL COMMENT '结束时间', 
    city_id INT(11) NOT NULL, 
    PRIMARY KEY (id), 
    INDEX idx_city_id (city_id), 
    INDEX idx_start_time (start_time) 
);

         建表完成后,插入了几条数据,执行以下语句验证

EXPLAIN SELECT * FROM test WHERE start_time = '2021-11-12 11:00:00' OR city_id=4;

        其中,start_time 和 city_id都有索引,然而结果却跟预期不符合,并没有使用到任何索引。

        这跟文章说的结论不符,那么问题出在哪里呢?原来是某些情况,例如小表,走索引查询的效率比全表扫描的代价更大,此时优化器会选择扫描全表。

        我切换了个大表,其中  id为主键索引,create_by为普通索引,执行以下语句:

 explain select * from xxx_media where id=1 or create_by='1'

        结论:由此之前一直背诵的索引失效情况:如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 。此说法不完全准确——注意:要想使用or,又想让索引生效,需要能将 or 条件中的每个列都加上索引

参考:

         mysql索引失效的几种原因 - ityangshuai - 博客园

         MySQL 优化之 index merge(索引合并) - digdeep - 博客园

        OR查询是否会使得索引失效? - 香菜多一点 - 博客园

疑问点2

        为什么存在两个索引的情况下却只使用了一个索引呢?

        与其说是数据库只支持一条查询语句只使用一个索引,倒不如说N条独立索引同时在一条语句使用的消耗比只使用一个索引还要慢。和全表扫描/只使用一个索引的速度比起来,去分析两个索引二叉树更加耗费时间,所以绝大多数情况下数据库都是是用一个索引。

        之前优化慢查询的时候,第一反应是——出现慢查了,那就为为where条件中的字段加索引。却没有深入思考怎么恰当加索引,仿佛理所当然的认为每个字段都有单索引,那么查询的时候都会用上。其实是不对的,所以需要掌握好explain给出的指引,利用好组合索引、索引覆盖、索引下推这些知识,才能优化好慢查询。

参考:

      MySQL数据库查询记录时是否每次只能使用一个索引_小太阳啊凯的博客-CSDN博客_mysql只能使用一个索引

      https://segmentfault.com/q/1010000003880137

 反思1

        MySQL单列索引和组合索引的选择效率

        如果查询语句的where条件只有一个,完全可以用单列索引,这样的查询速度较快,索引也比较瘦身。如果业务场景是需要经常查询多个组合列,不要试图分别基于单个列建立多个单列索引(因为虽然有多个单列索引,但是MySQL只能用到其中的那个它认为似乎最有效率的单列索引)。这是因为当SQL语句所查询的列,全部都出现在复合索引中时,此时由于只需要查询索引块即可获得所有数据,当然比使用多个单列索引要快得多。就算不能索引覆盖,也能通过多个索引字段过滤更多不符合的数据,减少回表的次数,达到加快查询速度的效果。

参考:       MySQL单列索引和组合索引的选择效率与explain分析_fanblog的博客-CSDN博客_mysql 单个索引和组合索引

反思2

        MYSQL EXPLAIN解析一 EXTRA中的USING INDEX,USING WHERE,USING INDEX CONDITION

        在进行慢查询优化时,我们经常会使用 explain 的结果来查看优化的程度,指导我们如何优化,我们比较关注里面 extra 字段。为表添加了索引以后,可以通过explain 查看优化后的 extra 字段的结果:

        using index :使用覆盖索引的时候就会出现;

        using where:在查找使用索引的情况下,部分条件在索引里面能找到,需要回表去查询所需的数据,然后再用剩下的条件过滤;

        using index condition:查找使用了索引下推,但是需要回表查询数据;

        using index & using where:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据。

参考:       MYSQL EXPLAIN解析一 EXTRA中的USING INDEX,USING WHERE,USING INDEX CONDITION_黄树茂博客-CSDN博客

       mysql explain解析一 extra中的using index,using where,using index condition - zhp_king - 博客园

        Mysql性能优化:什么是索引下推? - 爱撒谎的男孩 - 博客园

以上是关于MySQL慢查询优化实践小结的主要内容,如果未能解决你的问题,请参考以下文章

MySQL慢查询优化实践小结

MySQL慢查询优化实践小结

mysql性能优化-慢查询分析,优化索引最佳实践

MySQL慢日志查询实践

数据库基础干货MySQL基础及慢查询优化实践

数据库基础干货MySQL基础及慢查询优化实践