看一下accurate_result = 1的记录数
select count(*),accurate_result from stage_poi group by accurate_result;+----------+-----------------+| count(*) | accurate_result |+----------+-----------------+| 1023 | -1 || 2114655 | 0 || 972815 | 1 |+----------+-----------------+我们看到accurate_result这个字段的区分度非常低 , 整个表只有-1,0,1三个值 , 加上索引也无法锁定特别少量的数据
再看一下sync_status字段的情况
select count(*),sync_status from stage_poi group by sync_status;+----------+-------------+| count(*) | sync_status |+----------+-------------+| 3080 | 0 || 3085413 | 3 |+----------+-------------+同样的区分度也很低 , 根据理论 , 也不适合建立索引
问题分析到这 , 好像得出了这个表无法优化的结论 , 两个列的区分度都很低 , 即便加上索引也只能适应这种情况 , 很难做普遍性的优化 , 比如当sync_status 0、3分布的很平均 , 那么锁定记录也是百万级别的
4.找业务方去沟通 , 看看使用场景 。业务方是这么来使用这个SQL语句的 , 每隔五分钟会扫描符合条件的数据 , 处理完成后把sync_status这个字段变成1,五分钟符合条件的记录数并不会太多 , 1000个左右 。了解了业务方的使用场景后 , 优化这个SQL就变得简单了 , 因为业务方保证了数据的不平衡 , 如果加上索引可以过滤掉绝大部分不需要的数据
5.根据建立索引规则 , 使用如下语句建立索引
alter table stage_poi add index idx_acc_status(accurate_result,sync_status);6.观察预期结果,发现只需要200ms , 快了30多倍 。
952 rows in set (0.20 sec)我们再来回顾一下分析问题的过程 , 单表查询相对来说比较好优化 , 大部分时候只需要把where条件里面的字段依照规则加上索引就好 , 如果只是这种“无脑”优化的话 , 显然一些区分度非常低的列 , 不应该加索引的列也会被加上索引 , 这样会对插入、更新性能造成严重的影响 , 同时也有可能影响其它的查询语句 。
所以我们第4步调差SQL的使用场景非常关键 , 我们只有知道这个业务场景 , 才能更好地辅助我们更好的分析和优化查询语句 。
慢查询的案例就分析到这儿 , 以上只是一些比较典型的案例 。
【阿里P8架构师谈:MySQL数据库的索引原理、与慢SQL优化的5大原则】我们在优化过程中遇到过超过1000行 , 涉及到16个表join的“垃圾SQL” , 也遇到过线上线下数据库差异导致应用直接被慢查询拖死 , 也遇到过varchar等值比较没有写单引号 , 还遇到过笛卡尔积查询直接把从库搞死 。再多的案例其实也只是一些经验的积累 , 如果我们熟悉查询优化器、索引的内部原理 , 那么分析这些案例就变得特别简单了 。
推荐阅读
- 解密电商系统架构发展历程
- 前阿里ET实验室硬件负责人加盟易控智驾,看矿区自动驾驶如何掘金
- Hbase架构详解
- 带你深入了解高并发架构
- 网站架构模式
- Java反射机制是开发第三方架构的基础
- 微信小程序架构原理
- Apache Beam 架构原理及应用实践
- 微服务架构如何实现网站服务垂直化拆分
- 详细讲解Tomcat系统架构
