MYSQL 查询优化之路-之DISTINCT全表扫描

背景:今天对一个20w的表作关联查询,建立各类索引,没有提升执行的效率,使用EXPLAIN检查,老是提示“Using temporary”全表扫描,这不是我想的。经过度娘,各类百度,是由于DISTINCT使用了全表扫描,如今特别记录下来。以背查验。html

参考:
https://www.cnblogs.com/uttu/p/6384541.html
https://blog.csdn.net/songxixi/article/details/8475747
附网上一个同窗的分析,你们能够参考
须要优化的查询:使用explain
     出现了Using temporary;
     有分页时出现了Using filesort则表示使用不了索引,须要根据下面的技巧来调整语句
     rows过多,或者几乎是全表的记录数;
     key 是 (NULL);
     possible_keys 出现过多(待选)索引。
 
1.使用explain语法,对SQL进行解释,根据其结果进行调优:
     MySQL 表关联的算法是 Nest Loop Join,是经过驱动表的结果集做为循环基础数据,而后一条一条地经过该结果集中的数据做为过滤条件到下一个表中查询数据,而后合并结果:
          a.EXPLAIN 结果中,第一行出现的表就是驱动表
 
          b.对驱动表能够直接排序,对非驱动表(的字段排序)须要对循环查询的合并结果(临时表)进行排序(Important!),即using temporary;
 
          c. [驱动表] 的定义为:1)指定了联接条件时,知足查询条件的记录行数少的表为[驱动表];2)未指定联接条件时,行数少的表为[驱动表](Important!)。
 
          d.优化的目标是尽量减小JOIN中Nested Loop的循环次数,以此保证:永远用小结果集驱动大结果集(Important!)!:A JOIN B,A为驱动,A中每一行和B进行循环JOIN,看是否知足条件,因此当A为小结果集时,越快。
          
          e.NestedLoopJoin实际上就是经过驱动表的结果集做为循环基础数据,而后一条一条的经过该结果集中的数据做为过滤条件到下一个表中查询数据,而后合并结果。若是还有第三个参与Join,则再经过前两个表的Join结果集做为循环基础数据,再一次经过循环查询条件到第三个表中查询数据,如此往复
 
2.两表JOIN优化:
     a.当无order by条件时,根据实际状况,使用left/right/inner join便可,根据explain优化 ;
     b.当有order by条件时,如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解释语句;
     1)若是第一行的驱动表为a,则效率会很是高,无需优化;
     2)不然,由于只能对驱动表字段直接排序的缘故,会出现using temporary,因此此时须要使用STRAIGHT_JOIN明确a为驱动表,来达到使用a.col上index的优化目的;或者使用left join且Where条件中不含b的过滤条件,此时的结果集为a的全集,而STRAIGHT_JOIN为inner join且使用a做为驱动表
 
3.多表JOIN优化:
     a.无order by条件时,根据实际状况,使用left/right/inner join便可,根据explain优化;
     b.有order by a.col条件时,全部join必须为left join,且每一个join字段都建立索引,同时where条件中只能有a表的条件,即将其它表的数据关联到a中造成一张大表,再对a的全集进行过滤;
          若是不能全使用left join,则需灵活使用STRAIGHT_JOIN及其它技巧,以时间排序为例:
               1)数据入库按照平台时间入库,天然a的数据都按时间有序;
SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c STRAIGHT_JOIN res_node r ON c.res_node_id = r.ID STRAIGHT_JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 STRAIGHT_JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 limit 1,10;
 
SELECT c.*, r.HYPERVISOR_HOST_NAME hostname, r.HOST_IP FROM trust_monitor c inner JOIN res_node r ON c.res_node_id = r.ID INNER JOIN am_assets a ON r.ASSET_ID = a.ID AND a.status = 58 INNER JOIN se_role s ON a.DEPT_FLAG = s.ROLE_ORG AND s.ROLE_ID IN (32,33,36,41) where c.STATUS = 58 and c.changed_type = 79 order by c.changed_time limit 1,10;
二者结果一致
 
4.误区:
     a.视图只是屏蔽或者高效集合多表数据的一种方法,视图与表JOIN,不会起到任何效果node

相关文章
相关标签/搜索