exists 和 in 找了很久,唯一一篇比较透彻的。

来源:互联网 发布:钉宫骂观众 知乎 编辑:程序博客网 时间:2024/09/21 08:57
--1.  请查询出客户表中重名的人(以lastname进行判断)--使用exitsselect * from customers c1where exists(      select lastname       from customers c2      group by c2.lastname      having count(*)>1 and c1.lastname = c2.lastname);--使用in()select * from customers c1where c1.lastname in(      select lastname       from customers c2      group by c2.lastname      having count(*)>1);


一、使用in()语句,程序的过程可理解为:

List resultSet=[];
Array c1=(select * from customers
);Array c2=(select lastname from customers group by lastname having count(*)>1);
for(int i=0;i<c1.length;i++) {
   for(int j=0;j<c2.length;j++) {
      if(c1[i].id==c2[j].id) {
         resultSet.add(c1[i]);
         break;
      }
   }
}
return resultSet;

在这里in()子句中的查询只会执行一次,将查找到的lastnam缓存起来,然后与c1中的lastname逐一比对,如果相等,则将这条数据存入结果集,直到遍历完c1中的所有记录。

如:c1表有10000条记录,c2表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.

再如:c1表有10000条记录,c2表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.

结论:in()适合C2表(子查询的表)比C1(主表)表数据小的情况可以看出,当C2表数据较大时不适合使用in(),因为它会C2表数据全部遍历一次.

 

二、使用exists()语句,程序的过程可理解为:

List resultSet=[];
Array c1=(select * from customers)

for(int i=0;i<c1.length;i++) {
    if(exists(c1[i].lastname) {    //执行select 字句是否有记录返回
       resultSet.add(c1[i]);
    }
}
return resultSet;

当C2表比C1表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
如:C1表有10000条记录,C2表有1000000条记录,那么exists()会执行10000次去判断C1表中的lastname是否与C2表中的lastname相等.
如:C1表有10000条记录,C2表有100000000条记录,那么exists()还是执行10000次,因为它只执行C1.length次,可见B表数据越多,越适合exists()发挥效果.
再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

结论:exists()适合B表比A表数据大的情况

对于in 和 exists的性能区别: 

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

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

 


原创粉丝点击