【线上SQL优化复盘】

MySQL 线上性能优化实战(无八股、纯线上问题记录解决以及心得)

最近终于有时间可以来跟大家分享一下之前参与的一个项目上线遇到的性能问题:大部分问题都由于慢SQL导致
阅读本篇文章,你将获得以下收获:

  • SQL实际优化案列
  • 除了常见八股索引失效之外:排序字段编码不一致导致索引失效(即使使用use、force index关键字也无法解决)
  • 深入理解Innodb引擎中B+树索引
  • 理解随机IO、以及顺序IO
  • 了解MySQL优化器是如何选择最优索引的

背景:项目测试上线,系统非常不稳定,小程序、app端、PC端都非常的卡顿、进入系统后也非常的卡顿(当时遇到2个难题)
后面运维排查了一下,发现数据库所在的服务器的磁盘IO非常高(而且数据库会偶发性崩掉),后面重启后开启了慢日志查询,把大部分慢sql都打印出来了,除此之外,在连续的几天的观测发现,system服务的内存一直涨(即使流量高峰过去了,内存监控都没有落下来,而且还中途还出现过一次部分集群节点OOM killed重启)
难题1:慢查询SQL优化
难题2:system服务POD内存泄漏导致OOM Killed(这个是笔者发现的)

笔者在其中主要负责慢SQL的优化工作、system服务内存泄漏(OOM killed)问题排查以及保证xx模块上线的稳定

1、 SQL实际优化案列

1.1 索引失效、force index 失效均失效场景

原sql如下

> select
> 		su.realname as name,
> 		su.user_type,
>		sii.total_period as hours
> 		from study_user_record_statistic sii 
> 		join sys_user su on sii.user_id = su.id
> 		where su.org_code = 'xxxxxxx'
> 		order by sii.total_period desc

以上sql,通过explain 分析发现,study_user_record_statistic 表查询的时候,走的全表扫描;sys_user 表查询的时候,走的org_code_IDX

表数据情况:
sys_user 100w左右
study_user_record_statistic 85w左右
未优化之前,sql查询耗时:15s左右,explain 分析是因为study_user_record_statistic 未使用user_id索引导致全表扫描

当时推测造成索引失效的情况如下:

(1)mysql误判:索引user_id的cordinoritty 值未更新,与表中数据的区分度差别太大等导致sql索引优化器更倾向于走全表
后面低峰期的时候,更新了cordinoritty 且统计了一下user_id在study_user_record_statistic 表中的区分度还是很高的,排除这种可能
(2)使用原sql添加force index(user_id_IDX),explain 发现study_user_record_statistic 任然全表扫描,且key关键字为null
当时很纳闷,难道force index 失效了,不应该哇,但是在extra栏,看到一个以前没见过的标识,后面才发现study_user_record_statistic 中user_id的排序编码和sys_user 的id排序编码不一致
后面推测应该是数据工程师做数据迁移的时候造成的

解决方法也就明了:将关联字段的排序规则设置一致,explain 分析之后,sql使用了索引,查询平均时间降到了0.4~0.6s左右

1.2 mapper层编写复杂sql导致sql查询时产生中间表,同时由于临时生成的中间表数据量过大导致对应数据库节点直接崩掉

问题现象:点击页面对应功能,页面一直转圈
后面运维发现,说磁盘IO非常高,而且产生了2个T的中间表文件
笔者当时拿到sql之后,通过navcat去备份库做了查询,根本查不出数据来

导致原因:sql查询设计2张表,通过join关联同时还有union all,其中一张表数据量几千万,另外一张表100多万,由于关联查询产生中间表数据过大导致数据库崩溃

解决方案:找产品沟通理解对应功能点业务,重构mapper中的sql,最后sql执行的平均时间优化到了0.8~1.5s(具体笔者也记不清了)

1.3 未完待续

2、B+树索引

3、MySQL优化器是如何选择最优索引的(基于成本模型(因子))

4、sql优化总结

  • 操作规范
  • 定期更新表的索引统计:使用 ANALYZE TABLE 语句使表统计信息保持最新 定期

由于时间因素,笔者先分享这么多,后续有时间会继续在此篇文章的基础上更新

参考资料

MySQL5.7官方手册
MySQL之Innodb引擎第二版
高性能MySQL第三版

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值