转: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(); for(int 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,那么先执行子查询,所以我们会以驱动表的快速返回为目标