深入分析慢SQL的排查、解决思路

大促备战,最大的隐患项之一就是慢sql,对于服务平稳运行带来的破坏性最大,也是日常工作中经常带来整个应用抖动的最大隐患,在日常开发中如何避免出现慢sql,出现了慢sql应该按照什么思路去解决是我们必须要知道的。本文主要介绍对于慢sql的排查、解决思路,通过一个个实际的例子深入分析总结,以便更快更准确的定位并解决问题。
一、解决步骤
step1、观察sql
出于一些历史原因有的sql查询可能非常复杂,需要同时关联非常多的表,使用一些复杂的函数、子查询,这样的sql在项目初期由于数据量比较少,不会对数据库造成较大的压力,但是随着时间的积累以及业务的发展,这些sql慢慢就会转变为慢sql,对数据库的性能产生一定的影响。
对于这样的sql,建议先了解业务场景,梳理关联关系,尝试将sql拆解为几个简单的小sql,在内存中关联组合。
step2、分析问题
大家在分析慢sql时最常用的工具肯定是explain语句,如下是explain语句的执行输出。
一般情况下我们最需要关注的指标有type、possible_keys、key、rows、extra几项。
type为连接类型,有如下几种取值,性能从好到坏排序如下:
system:该表只有一行(相当于系统表),system是const类型的特例
const:针对主键或唯一索引的等值查询扫描, 最多只返回一行数据. const 查询速度非常快, 因为它仅仅读取一次即可
eq_ref:当使用了索引的全部组成部分,并且索引是primary key或unique not null 才会使用该类型,性能仅次于system及const。
ref:当满足索引的最左前缀规则,或者索引不是主键也不是唯一索引时才会发生。如果使用的索引只会匹配到少量的行,性能也是不错的。
tips
最左前缀原则,指的是索引按照最左优先的方式匹配索引。比如创建了一个组合索引(column1, column2, column3),那么,如果查询条件是:
where column1 = 1、where column1= 1 and column2 = 2、where column1= 1 and column2 = 2 and column3 = 3 都可以使用该索引;
where column2 = 2、where column1 = 1 and column3 = 3就无法匹配该索引。
fulltext:全文索引
ref_or_null:该类型类似于ref,但是mysql会额外搜索哪些行包含了null。这种类型常见于解析子查询
index_merge:此类型表示使用了索引合并优化,表示一个查询里面用到了多个索引
unique_subquery:该类型和eq_ref类似,但是使用了in查询,且子查询是主键或者唯一索引。例如:
index_subquery:和unique_subquery类似,只是子查询使用的是非唯一索引。
range:范围扫描,表示检索了指定范围的行,主要用于有限制的索引扫描。比较常见的范围扫描是带有between子句或where子句里有>、>=、<、= '2023-03-26 0000' and r.update_time <= '2023-04-02 0000' and r.yn = 1 and v.yn = 1 and d.yn = 1 and d.status != -1 and ifnull(r.carrier_individual_type,'') != '2'order by (case r.verify_status when 30 then 1 when 20 then 2 when 25 then 3 when 35 then 4 when 1 then 5 else 6 end), r.update_time desc, if((v.driving_license_time is null and d.driver_license_time is null), 0, 1) desc, if(((v.driving_license_time is not null and v.driving_license_time < now()) or (d.driver_license_time is not null and d.driver_license_time < now())), 2, 0) desc limit 10;
实际开发过程中还有许多从sql本身不好优化的场景,比如查询数据加载过多、表数据量过大、数据倾斜严重等等,尽量根据业务场景进行一些必要的保护措施限制,在不影响业务的情况下寻找替代方案,例如使用es进行查询,不过还是需要根据实际的场景选择不同的方式解决。
7、对于一些较大数据量的表,在进行分页查询的时候其实很快就能返回结果,但是在进行分页count总条数时往往很慢,这是因为在分页查询时会有pagesize的限制,当mysql查询到满足条数的数据后就会直接返回,而在进行count时则会根据条件全表查询,当条件包含的数据量过大时就会限制sql的性能。这种情况下建议一方面将分页逻辑重写,分离count和selectlist,可以考虑应用es作为count数据来源,或在某些条件下如果已存在总条数则不再count,减少分页count的次数;另一方面限制分页深度避免出现深分页。
三、总体优化原则
创建合适的索引
减少不必要访问的列
使用覆盖索引
语句改写
数据结转
选择合适的列进行排序
适当的列冗余
sql拆分
适当应用es


iPhone8欲哭无泪:黑科技太多 工艺太高端 结果生产困难
小米智能电视连续7个季度大陆出货量第一
怎么区分单层/双面/多层FPC?
微芯科技推出全新下桥臂MCP14E6系列驱动器
4路电话录音盒
深入分析慢SQL的排查、解决思路
数字标牌的运营,将会开启教育行业的里程碑
Gresso 3310:纯手工打造,价格完爆苹果
谷波推出40/50/65G高速板端连接器,填补国产空白
Si、SiC和GaN这三种材料共存,到底该如何选择
5G独立组网标准有望下月发布确立
一锁当关万夫莫开,TCL物联网智能锁K2暗藏硬核科技
Fitbit官方宣布受中美贸易冲突影响生产从中国迁走
帕西尼感知科技完成数千万Pre-A轮融资,专注于高精度触觉传感器研发
利用Smart组件制作秒针的详细步骤
全球企业正在加速数字化战略转型,构建全新经营模式
VR/AR正在改变着网页设计行业
流量计在植保无人机上的应用
服务器或者网站如何才能不被DDOS攻击
符合IEC 61851-1、VDE 0122-1 标准的便携式交流充电桩测试仪