• oracle中的exists 和 in 用法详解


    以前一直不知道exists和in的用法与效率,这次的项目中需要用到,所以自己研究了一下。下面是我举两个例子说明两者之间的效率问题。

    前言概述:

    “exists”和“in”的效率问题,涉及到效率问题也就是sql优化:

    1.若子查询结果集比较小,优先使用in。

    2.若外层查询比子查询小,优先使用exists。原理是:若匹配到结果,则退出内部查询并将条件标志为true,传回全部结果资料

    因为若用in,则oracle会优先查询子查询,然后匹配外层查询,原理是:in不管匹配到匹配不到都全部匹配完毕,匹配相等就返回true,就会输出一条元素.

    若使用exists,则oracle会优先查询外层表,然后再与内层表匹配

    也就是:”匹配原则,拿最小记录匹配大记录。也就是遍历的次数越少越好"

    例子如下:

    1) select * from T_USER1 where exists(select 1 from T_USER2 where T_USER1.jxb_id =T_USER2.jxb_id ) ;

        T_USER1 数据量小而T_USER2 数据量非常大时,T_USER1 <<T_USER2  时,1) 的查询效率高。

    原理解析:以上查询使用了exists语句,sql语句如:select a.* from A a where exists(select 1 from B b where a.id=b.id)

    exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.
    它的查询过程类似于以下过程:

    1 List resultSet=[];
    2 Array A=(select * from A)
    3 
    4 for(int i=0;i<A.length;i++) {        //这个循环次数越少越好
    5    if(exists(A[i].id) {    //执行select 1 from B b where b.id=a.id是否有记录返回
    6        resultSet.add(A[i]);
    7    }
    8 }
    9 return resultSet;

    当B表比A表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
    如:A表有10000条记录,B表有1000000条记录,那么exists()会执行10000次去判断A表中的id是否与B表中的id相等.
    如:A表有10000条记录,B表有100000000条记录,那么exists()还是执行10000次,因为它只执行A.length次,可见B表数据越多,越适合exists()发挥效果

    再如:A表有10000条记录,B表有100条记录,那么exists()还是执行10000次,还不如使用in()遍历10000*100次,因为in()是在内存里遍历比较,而exists()需要查询数据库,我们都知道查询数据库所消耗的性能更高,而内存比较很快.

    2) select * from T_USER1  where T_USER1.jxb_id in (select T_USER2 .jxb_id from T_USER2 ) ;

         T_USER1 数据量非常大而T_USER2数据量小时,T_USER1 >>T_USER2时,2) 的查询效率高。

    原理解析:这里有条SQL语句:select * from A where id in(select id from B) 

    以上查询使用了in语句,in()只执行一次,它查出B表中的所有id字段并缓存起来.之后,检查A表的id是否与B表中的id相等,如果相等则将A表的记录加入结果集中,直到遍历完A表的所有记录;

    它的查询过程类似于以下过程

    List resultSet=[];
    Array A=(select * from A);
    Array B=(select id from B);
    
    for(int i=0;i<A.length;i++) {
       for(int j=0;j<B.length;j++) {
          if(A[i].id==B[j].id) {
             resultSet.add(A[i]);
             break;
          }
       }
    }
    return resultSet;

    可以看出,当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
    如:A表有10000条记录,B表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差.
    再如:A表有10000条记录,B表有100条记录,那么最多有可能遍历10000*100次,遍历次数大大减少,效率大大提升.

    =======================================================================================================

    详解上面的用法:

    exists 用法:

    其中 “select 1 from T_USER2 where T_USER1.jxb_id =T_USER2.jxb_id” 相当于一个关联表查询,相当于

    “select 1 from T_USER1,T_USER2  where T_USER1.jxb_id=T_USER2.jxb_id”

    这种情况下不能单独执行select 1那部分的sql,不然会报语法错误的,这也是使用exists需要注意的地方。

    “exists(xxx)”就表示括号里的语句能不能查出记录,它要查的记录是否存在。

    因此“select 1”这里的 “1”其实是无关紧要的,换成“*”也没问题,它只在乎括号里的数据能不能查找出来,是否存在这样的记录,如果存在,这 1) 句的where 条件成立。

    ==============================

    in 的用法:

    “2) select * from T_USER1  where T_USER1.jxb_id in (select T_USER2 .jxb_id from T_USER2 ) ;

    这里的“in”后面括号里的语句搜索出来的字段的内容一定要相对应,一般来说,T1和T2这两个表的a字段表达的意义应该是一样的,否则这样查没什么意义。注意:两个字段名称可以不同,但是代表的东西一定是一样的才可以。

    打个比方:T1,T2表都有一个字段,表示工单号,但是T1表示工单号的字段名叫“ticketid”,T2则为“id”,但是其表达的意义是一样的,而且数据格式也是一样的。这时,用 2)的写法就可以这样:

    1 “select * from T1 where T1.ticketid in (select T2.id from T2) ”
    2 
    3 Select name from employee where name not in (select name from student);
    4 
    5 Select name from employee where not exists (select name from student);

    第一句SQL语句的执行效率不如第二句。

    总结:

    通过使用EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。

    Oracle在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。

    这也就是使用EXISTS比使用IN通常查询速度快的原因

  • 相关阅读:
    git如何将一个远程仓库的某个分支拉取到当前分支?
    linux下如何检查内核补丁是否符合社区代码规范?
    javascript快速入门20--Cookie
    javascript快速入门19--定位
    javascript快速入门18--样式
    javascript快速入门17--事件
    javascript快速入门16--表格
    javascript快速入门15--表单
    javascript快速入门15--节点
    javascript快速入门14--DOM基础
  • 原文地址:https://www.cnblogs.com/caiguangbi-53/p/9546239.html
Copyright © 2020-2023  润新知