定位低效率sql

对于mysql性能优化,除了宏观层面的网络、设备等优化,sql语句的优化是极为重要的一环,需要想办法找到对应的执行效率低的sql语句进行优化。

慢查询日志

慢查询日志是定位低效率sql的手段之一,通过以下命令,设置开启慢查询日志。

#显示是否开启了慢查询日志

show variables like 'slow_query_log';

#开启慢查询日志

set global slow_query_log = on

#慢查询日志输出位置

set global slow_query_log_file = '/var/lib/mysql/gupaoedu-slow.log'

set global log_queries_not_using_indexes = on

#设置耗时查询时间阈值

set global long_query_time = 0.1

有了慢查询日志之后,可以通过mysqldumpslow分析哪一条sql语句需要进行优化,建立合适的索引。

Druid数据源的监控

使用阿里的Druid数据源时可以对接自带的监控平台,非常方便有各种统计数据,可以监控慢sql

业务定位

这个就非常粗暴了,只管堆数据,然后看接口的效率,可以粗略定位sql语句

explain输出格式含义分析

explain输出格式含义,这一个在mysql官网有完整的解释,奈何英语水平有限,看的难受,幸好发现这位博主的一篇文章,解释的非常全面,易懂,强烈推荐EXPLAIN用法和结果分析,了解的explain的输出含义,才能做以下分析。

深入了解explain结果分析,了解每种情况会出现什么样的explain结果输出,以此能够更加清晰明了、正确地使用索引。

根据explain分析索引有效性

假设有如下表结构,创建主键为id,联合索引为(biz_no,cus_code),单列唯一索引uni_no

-- auto-generated definition

create table index_test

(

id int auto_increment

primary key,

biz_no varchar(11) default '' not null,

cus_code varchar(11) default '' not null,

uni_no varchar(11) default '' not null,

constraint idx_biz_no_cus_code

unique (biz_no, cus_code),

constraint uk_uni_no

unique (uni_no)

);

执行以下存储过程,插入数据。

#定义存储过程

delimiter //

DROP PROCEDURE IF EXISTS insert_test_val;

##num_limit 要插入数据的数量,begin_num 起始数字

CREATE PROCEDURE insert_test_val(in num_limit int,in begin_num int)

BEGIN

DECLARE i int default 1;

DECLARE a varchar(11) default '';

DECLARE b varchar(11) default '';

DECLARE c varchar(11) default '';

WHILE i<=num_limit do

set a = concat('bizno',begin_num);

set b = concat('cus',begin_num);

set c =concat('uni',begin_num);

INSERT into index_test(biz_no, cus_code, uni_no) values (a,b,c);

set i = i + 1;

set begin_num = begin_num + 1;

END WHILE;

END

#调用存储过程

call insert_test_val(200000,1);

单列索引

在where条件中不同的使用方式可能会对索引的有效性有不同的影响,这里简单分析几种情况。

情况1:key=?情况

对于单列索引,最常见的是key=?的情况,例如针对上面的表结构,执行以下sql,分析explain结果。

explain select * from index_test where uni_no='uni500';

执行结果如下

可以看出,type是const,表示是一次索引就能得到数据,索引有效。

如果我们了解innodb索引树的结构,应该可以知道,这里的索引过程应该是,先从辅助索引树uni_no的索引树检索得到主键id,然后还需要从主键索引树检索目标记录,因此除了能够使用索引之外,还可以进一步优化,就是根据业务需求,看能否使用上覆盖索引。

覆盖索引下

例如以下sql。只选择id的话,在辅助索引树就能完成,不需要再去主键索引树检索,大大提高了性能。

explain select id from index_test where uni_no='uni500';

情况2:key > ? | key < ?情况。

对于范围查询,会影响查询效率,这个是必然的,但是在范围条件中建立索引,能否够提升查询效率?

索引生效

执行如下sql,使用索引进行范围查询

select * from index_test where uni_no < 'uni10000';

结果是下图,只有四条记录。

执行explain sql分析执行计划,结果如下图,可以看出,这里的type使用的是range类型,也就是从指定的范围开始检索记录,uni_no索引生效。

反转,索引不生效

但是假如我们执行以下sql,把条件改为大于号,得到的explain输出确实不一样。

explain select * from index_test where uni_no > 'uni10000';

输出,此时执行的是全表扫描,索引不生效,这是为什么?

思考,为何范围查询索引时而生效时而不生效

我在数据库表中插入总共20万数据,其中条件为uni_no < 'uni10000'的数据只有四条。而反过来的数据则有199996条,约等于全表数据。我们可以知道在不是覆盖索引的情况下,使用辅助索引树检索数据需要检索两遍,假如mysql在uni_no索引树范围内逐条检索到199996条主键记录符合,然后每条主键记录都去主键索引树检索记录数据的话,效率还不如全表扫描。

因此执行计划对此有相应优化,如果查询优化器预计辅助索引树检索到的符合的记录量特别大的情况下,就不会使用辅助索引树查询,反而使用全表扫描来完成检索,例如uni_no > 'uni10000'的情况。反之,如果预计辅助索引树检索到的记录不多的情况下,还是会使用辅助索引来检索,例如uni_no < 'uni10000'的情况.

但是需要注意,非唯一索引树精确值等值检索,不管匹配多少记录,都是走索引树,不会因为匹配多了就不走索引树检索,猜测是因为非唯一索引树精确检索效率很高,type属于ref类型,因此先检索辅助索引树在检索主键索引树的效率还是比all全表要高。

再次思考,在单列覆盖索引的情况下,是否应该一直生效

根据上面的思考再次推论,在覆盖索引的情况下,检索数据不需要在辅助索引树和主键索引树分别检索两遍,只需要在辅助索引树检索就能得到对应数据,那么直接在辅助索引树上进行查询应该是最优的策略,推测不管是uni_no < 'uni10000'还是uni_no > 'uni10000',索引都应该生效。

执行以下sql验证。

explain select id from index_test where uni_no > 'uni10000';

explain select id from index_test where uni_no < 'uni10000';

结果查询的type都是range,索引生效,推测正确。

类比,其他索引时而生效时而不生效的情况

在key > ? | key < ?情况下,索引是否生效并不是绝对的。因为是范围查询,导致辅助索引树可能匹配到多条记录,然后到逐渐索引树检索,这种情况索引就不会生效,反而会使用all查询。其实类似的情形可以类比到一些辅助索引树匹配到记录比较多的情况。

order by或者group by索引时而生效时而不生效

例如本例子中,对比以下两个sql的输出,你会发现也是索引不一定生效的,type不一定是range,一切有查询优化器决定。

explain select * from index_test where biz_no > 'bizno10000' order by biz_no,cus_code;

#辅助索引匹配记录预计趋近全表,不使用索引

#输出,使用全表扫描,filesort外部排序

1SIMPLEindex_testALLidx_biz_no_cus_code199586Using where; Using filesort

#但是假如是覆盖索引,辅助树匹配记录预计趋近全表,则还是会使用索引排序,如下sql

explain select biz_no from index_test where biz_no > 'bizno10000' order by biz_no,cus_code;

#输出,使用range,索引排序

1SIMPLEindex_testrangeidx_biz_no_cus_codeidx_biz_no_cus_code1399793Using where; Using index

explain select * from index_test where biz_no < 'bizno10000' order by biz_no,cus_code;

#辅助索引匹配记录预计较少,

#输出,使用range,索引排序

1SIMPLEindex_testrangeidx_biz_no_cus_codeidx_biz_no_cus_code134Using where

order by或者group byPS分析总结:当order by出现filesort时考虑以下问题

order by条件是否已经建立索引?多个order by列时,还需要建立联合索引来提升,避免出现filrsort。

如果确认order by已经建立索引,那么再看看是否加了where条件和where条件是否走order by列的索引?如果不是就会出现filesort。如果where条件与order by使用的是同一个索引,还是出现filesort,继续往下看

如果where条件与order by使用的是同一个索引,还是出现filesort,考虑是不是where条件在辅助索引树匹配的记录太多,导致查询优化器直接不走索引树查询,如果是,请考虑控制where条件或者考虑配合业务手段,使用覆盖索引方式操作来达到走索引的目的。

当然,出现filesort并不是说就一定是大问题,如果select的explain 输出type是range以上,使用filesort也是可以接受的,只是如果对性能有很高要求时,可以考虑这样子去优化。

##这是一个查询类型是range,但是使用filesort的sql,效率也不差

explain select * from index_test where uni_no < 'uni10000' order by biz_no,cus_code;

#输出

1SIMPLEindex_testrangeuk_uni_nouk_uni_no134Using where; Using filesort

情况3:<> |!=

这些情况下不走索引,explain 输出type都是all

总结

单列索引有效性分析总结以下几点:

精确匹配索引生效

范围查找情况,索引生效判断依据以下规则:

覆盖索引下,范围查找索引一律生效

非覆盖索引查询,如果预计辅助索引树检索范围内匹配记录数据量较大,则索引不生效,做All扫描;

如果预计索引树检索范围内匹配记录数据量较小,则索引生效,做range类型查询。

order by、group by等没有使用索引排序出现filesort,参考PS分析总结

like的情况按照最左匹配原则生效

没使用索引精确或者范围查询,索引不可能生效。非等查询,索引也不能生效。

联合索引

分析联合索引的有效性时,首先需要知道的点是联合索引的匹配原则是最左匹配。

情况1:key1=? and key2=?

假如有联合索引(key1,key2),那么在完全精确匹配的情况下,索引是有效的,查询类型type是const,表示一次索引就能得到结果。例如以下例子。

explain select * from index_test where biz_no='bizno5000' and cus_code='cus5000';

输出如图所示

类似地,两列以上的联合索引精确匹配也是const类型查询。

情况二:key1=?

假如有联合索引(key1,key2),在没有精确匹配的情况下只使用key1=?作为索引条件,遵循最左匹配原则,只用最部分最左条件进行索引查询,索引生效情况如何?以下例子。

explain select * from index_test where biz_no='bizno5000';

结果输出如图下所示,可以看出查询类型下降一个级别,变成ref,索引可以匹配多条记录,但是效率依然很高,索引依然生效。

类似地,两列以上的联合索引,依据最左前缀原则匹配查询,查询type也是ref。例如联合索引(key1,key2,key3),使用where条件是key1=‘a’ and key2=‘b’,查询type也是ref。

精确查询与范围查询结合

类似地,假如最左列使用精确检索,右边列使用范围检索,精确查询效果如何?

explain select * from index_test where biz_no = 'bizno10000' and cus_code >= 'cus10000';

输出查询类型为ref,索引生效.

情况3:联合索引仅范围查询

跟单列索引一样,涉及到仅使用范围查询分析索引生效情况,必须分为是否是覆盖索引的查询来分析。要想仅使用范围查询,并且联合索引生效,还是需要按照最左前缀匹配,所以只有在最左列作为范围条件时才可能生效。因此最终的分析方式其实跟单列的索引范围查询一样分析。

非覆盖索引

辅助索引树匹配范围记录较少的情况?

使用最左列进行范围查询, biz_no < 'bizno10000’记录较少,只有四条。

explain select * from index_test where biz_no < 'bizno10000' ;

输出结果如下图所示,虽然使用了范围查询,但是辅助索引树预计范围内匹配记录数量较少,那么再次扫描主键索引树获取全部数据的消耗时间不会很高,因此还是使用查询类型type是range的查询。此时索引生效。

辅助索引树匹配范围记录较多的情况?

使用最左列进行范围查询, biz_no > 'bizno10000’记录趋近全表。

explain select * from index_test where biz_no > 'bizno10000' ;

输出结果如下图所示,联合索引的索引树预计范围内匹配的数据量比较大,再次扫描主键索引树获取全部数据的消耗时间可能较高,所以查询优化器优化决定使用全表扫描代替range查询。此时索引不生效。

覆盖索引

覆盖索引下,减少了再次扫描主键索引树的过程,那么其实不管联合索引的索引树匹配多少条记录都是无所谓的,因此都是使用range查询,索引都会生效。

例如匹配记录多的情况。

explain select biz_no from index_test where biz_no > 'bizno10000' ;

输出如下图所示,虽然预计扫描行数较多,但是还是使用range查询,索引生效,因为不需要再次扫描主键索引树,range查询联合索引树效率最高。Extra中的Using Index使用覆盖索引查询。

不用说,匹配记录少的情况同理也是一样。

总结

联合索引的索引生效原则如下:

所有列精确匹配索引一定生效

最左列精确匹配,右边列使用范围查询、非等查询、不使用右边列,索引一样生效。

最左列使用范围查询时:

如果是覆盖查询,索引一律生效

如果不是覆盖查询,当查询优化器预计范围匹配记录较大的时候,索引不生效;当查询优化器预计范围匹配记录较小的时候,索引生效。

如果最左列没使用精确或者范围查询,联合索引不可能生效。

like 查询跟单列索引类似,也是最左匹配原则。

mysql验证索引正确性_mysql调优--根据explain结果分析索引有效性,正确使用索引相关推荐

  1. linux mysql io压力大_MySQL 调优基础(四) Linux 磁盘IO_MySQL

    1. IO处理过程 磁盘IO经常会成为系统的一个瓶颈,特别是对于运行数据库的系统而言.数据从磁盘读取到内存,在到CPU缓存和寄存器,然后进行处理,最后写回磁盘,中间要经过很多的过程,下图是一个以wri ...

  2. MySQL优化filler值_MySQL 性能优化神器 Explain 使用分析

    简介 MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化. EXPLAIN 命令用法十分简单, 在 ...

  3. MySQL优化调优有没有做过_MySQL 调优/优化的 100 个建议

    MySQL是一个强大的开源数据库.随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈.这里提供 101 条优化 MySQL 的建议.有些技巧适合特定的安装环境,但是思路是相通的.我已经将它们分成 ...

  4. mysql100个优化技巧_MySQL 调优/优化的 100 个建议

    MySQL是一个强大的开源数据库.随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈.这里提供 101 条优化 MySQL 的建议.有些技巧适合特定的安装环境,但是思路是相通的.我已经将它们分成 ...

  5. mysql100多个字段如何优化_MySQL 调优/优化的 100 个建议

    MySQL是一个强大的开源数据库.随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈.这里提供 101 条优化 MySQL 的建议.有些技巧适合特定的安装环境,但是思路是相通的.我已经将它们分成 ...

  6. 第六章 模型的验证、监控与调优

    模型的验证.监控与调优 简介:得到评分卡模型后,还需要验证模型的性能.并且部署后还要持续监测模型的表现. 目录: 模型的区分度 模型的预测性与混淆矩阵 模型的平稳性 模型的调优 模型的区分度 区分度的 ...

  7. MYSQL企业常见架构与调优经验分享-高俊峰-专题视频课程

    MYSQL企业常见架构与调优经验分享-8967人已学习 课程介绍         爱维Linux独家发行,从MYSQL系统安装.配置入手,从多个方面深入介绍MYSQL的使用技巧和调优策略,大限度发挥M ...

  8. R语言使用caret包的train函数构建xgboost模型(基于linear算法)模型构建分类模型、trainControl函数设置交叉验证参数、自定义调优评估指标

    R语言使用caret包的train函数构建xgboost模型(基于linear算法)模型构建分类模型.trainControl函数设置交叉验证参数.自定义调优评估指标.tuneLength参数和tun ...

  9. R语言使用caret包的train函数构建xgboost模型(基于gbtree算法)模型构建分类模型、trainControl函数设置交叉验证参数、自定义调优评估指标

    R语言使用caret包的train函数构建xgboost模型(基于gbtree算法)模型构建分类模型.trainControl函数设置交叉验证参数.自定义调优评估指标.tuneLength参数和tun ...

最新文章

  1. 安装eclipse时一直跳转JRE Missing页面
  2. OKR 怎么突然火起来了?
  3. APT-高级软件包管理
  4. ASP.NET Core MVC 源码学习:详解 Action 的匹配
  5. 开源推荐:.Net Core3.1 + EF Core + LayUI 封装的MVC版后台管理系统
  6. css设置鼠标滑过背景变色;鼠标滑过背景变色
  7. QT中生成字符串md5的方法
  8. Windows 10开机可以跳过锁屏界面的操作方法
  9. 过剩通勤应用——线性规划问题解决开源工具(下篇)
  10. Swift观察者模式
  11. aspcms基本的安全策略
  12. 北邮计算机学院专业分析,2019-2021北京邮电大学考研数据分析
  13. 三部门禁止对新能源车限购 专家:京沪情况复杂,政策仍不明朗
  14. android 一分钟倒计时动画,Android利用属性动画自定义倒计时控件
  15. Opencv3基础操作3——图像形态学处理
  16. 持续更新,mysql的复习强化路
  17. iFunk执政官游戏本强势上线,开启畅玩之旅
  18. 新春特别策划:新春观影 与科幻电影难分舍的IT元素
  19. 【搭建jekins】
  20. 基于matlab的静电场边值,典型静电场场图解析解(含Matlab程序).pdf

热门文章

  1. 【jumpserver升级】docker pulling image报错dial tcp 104.18.124.25:443: i/o timeout
  2. podman容器的开机自启
  3. 《Web GIS原理与应用开发》读书笔记(1)
  4. 无感刷新token方法
  5. asp版茶叶礼品卡券、海鲜礼品卡券、大闸蟹礼品卡券、龙虾礼品卡券-提货系统-生成卡密源码
  6. 什么是SCI期刊分区,让你一次搞懂!
  7. JPEG图片编码格式分析
  8. 【对讲机的那点事】公网对讲机使用的物联卡你了解吗?
  9. php 微信公众号 修改图片尺寸_php微信公众号开发之图片回复
  10. 位运算概览与奇巧淫技