mysql15 sql优化-小表驱动大表 IN和EXITS

转:https://blog.csdn.net/qq_27409289/article/details/85963089


1、IN查询分析

select * from a  where a.id in( select a_id from b )

相当于:

Object[] out={select *  from a};

Object[] in={select *  from a};

List<Object> result=new ArrayList();

for(int i =0;  i<>out.size();i++)

                 {

                     for (int j = 0 ; j<in.size(),j++){

                         if(out[i].id=in[j]){

                               result.add(out[i]));

                            }
                      }
                }

在内存中进行比对,最大的比对数可以达到外层结果集*内层结果集

2、EXISTS查询分析

select * from a where exist(select 1  from b.a_id=a.id);


相当于:

Object[] out={select *  from a};

        List<Object> result=new ArrayList();

       forint i=0;i<out.size();i++){

              //子查询(内查询)

               //1 去查询数据库

               // 2 判断外部数据的值执行第一步是是否能查到数据,返回 ture或者false 

              // 3 如果第二部为true

              if(exiset(out[i].id)){//执行  select * fron b where b.a_id=a.id;  会执行 out.size();次

                   result.add(out[i]));

               } 

       }

所以如果a表中的数据越大那么 子查询查询的次数就会越多,这样对效率就很慢

      例如:

        1 表a中100000条数据,表b中100条数据,查询数据库次数=1(表a查一次)+100000(子查询:查询表b的次数)  ,一共100001次

         2 表a中 100条数据,表b100000条,查询数据库次数=1(表a查一次)+100(子查询次数),一共 101次

         也就是说exits的查询次数=1+外层结果集的数量,可见只有当子查询的表数量远远大于外部表数据的用exist查询效率好


3.小结

  如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。

  其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标

原文地址:https://www.cnblogs.com/jthr/p/15380070.html