生产上面有一条sql查询很慢,须要7到8秒左右,简化以后的sql以下所示:mysql
SELECT mingxi.* FROM ( SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.inibeginmonth AS beginYearMonth, lsbtsj.btje AS btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND lsbtsj.btqsyf <='2019-10' AND lsbtsj.btjzyf >='2019-10' AND beginYearMonth != inibeginmonth UNION ALL SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.beginYearMonth, btjc01.btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040 WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND (beginYearMonth <='2019-10') ) AS mingxi LIMIT 100,200;
执行计划以下所示:sql
能够看到 执行计划里面出现了 Using intersect,btjc01046 btjc01048 btjc01037 btjc01047 多个索引来进行数据的过滤。mysql优化
另外发现一个问题,里面的 union all 子查询 却只须要 0.4秒就能够执行完成:优化
SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.inibeginmonth AS beginYearMonth, lsbtsj.btje AS btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND lsbtsj.btqsyf <='2019-10' AND lsbtsj.btjzyf >='2019-10' AND beginYearMonth != inibeginmonth UNION ALL SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.beginYearMonth, btjc01.btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040 WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND (beginYearMonth <='2019-10')
执行计划以下:blog
比较一下前面和后面两个的执行计划,能够发现 都是有了 Using intersect 可是呢后面一个却只须要0.4秒,而在外面加上一层 select * from t,时间却须要7到8秒。一直没有明白什么缘由。索引
最后的优化是去掉 Using interset ,使用 force index 手动指定使用索引 btjc01048:io
SELECT mingxi.* FROM ( SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.inibeginmonth AS beginYearMonth, lsbtsj.btje AS btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 force index(btjc01048) INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN lsbtsj ON lsbtsj.btrid = btjc01.Id WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND lsbtsj.btqsyf <='2019-10' AND lsbtsj.btjzyf >='2019-10' AND beginYearMonth != inibeginmonth UNION ALL SELECT btjc01.id, department.`name` AS btjc01011, btjc01011 AS obj, btjc01.beginYearMonth, btjc01.btjc01030, CASE WHEN btjc01.inibeginmonth ='2019-10' THEN '是' ELSE '否' END AS isadd FROM btjc01 force index(btjc01048) INNER JOIN department ON department.Id = btjc01.btjc01038 INNER JOIN btgg03 ON btgg03.Id = btjc01.btjc01040 WHERE btjc01.btjc01037 = '3' AND btjc01046 ='江西省' AND btjc01047 ='九江市' AND btjc01048 ='修水县' AND (beginYearMonth <='2019-10') ) AS mingxi LIMIT 100,200;
执行时间须要1.2秒左右,和0.4秒相比,仍是有差距。执行计划以下;class
能够看到没有了 Using interset. 咱们强制使用索引 btjc01048.select
总结:nio
若是出现 Using interset 须要注意是否mysql优化器选择的是不是最佳的索引方案。是否能够经过force index来选择更优的索引。