一、慢查询产生原因
大体有以下三种可能:
1、索引没有设计好;
2、SQL 语句没写好;
3、MySQL 选错了索引。
二、慢查询解决方案
1、针对索引没有设计好的解决方案:给表重新加索引重新加索引
2、针对SQL 语句没写好的解决方案:重写sql语句
【下一版本修复】:检查业务代码中的sql,是否使用了条件字段函数操作、是否有隐式转化【
①检查是否在搜索条件中使用了条件字段函数操作(例如month活动id+1=1000等),导致优化器放弃走树搜索功能,走全索引扫描
② 比如id值为string,查询语句用了int(对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。)
③ 由于字符集不同(utf8mb4),导致表连接查询的时候用不上关联字段索引,需要把转化放在条件=的后面,就可以使用索引
a、两张表的字符集改成统一
b、sql改写,需要把转化放在条件=的后面来使用索引】
【线上紧急修复】:数据库执行层:使用query_rewrite功能让执行的sql重写成可以使用索引的语句
3、针对MySQL 选错了索引的解决方案:
【线上紧急修复】:就是给这个语句加上 force index,使用查询重写功能,给原来的语句加上 force index,也可以解决这个问题。
【不紧急】:
① 使用force index:分析不同索引的查询条数,比如用索引a需要查询5000条、索引b需要查询1000条,此时明显选索引b查询效率更高,但是mysql优化器选择了索引a(因为优化器还会考虑回表、排序等综合因素导致选错),我们需要 force index与原sql做对比,根据结果考虑是否需要使用force index
② 改写语句:例如“select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;”语句中将”order by b limit 1” 改成 “order by b,a limit 1” ,要求按照 b,a 排序,就意味着使用这两个索引都需要排序。因此,扫描行数成了影响决策的主要条件
③在有些场景下,我们可以新建一个更合适的索引,来提供给优化器做选择,或删掉误用的索引。
三、预先检查方案:
1、上线前,在测试环境,把慢查询日志(slow log)打开,并且把 long_query_time 设置成 0,确保每个语句都会被记录入慢查询日志;
2、在测试表里插入模拟线上的数据,做一遍回归测试;
3、观察慢查询日志里每类语句的输出,特别留意 Rows_examined 字段是否与预期一致。
4、全量回归测试都是必要的。这时候,你需要工具帮你检查所有的 SQL 语句的返回结果。比如,你可以使用开源工具 pt-query-digest
来源地址:https://blog.csdn.net/weixin_43837268/article/details/129655778