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 - 博客园
疑问点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慢查询优化实践小结的主要内容,如果未能解决你的问题,请参考以下文章