zoukankan      html  css  js  c++  java
  • Oracle 中 not exists (select 'X' ...) 的含义

    select a.col1,a.col2 from temp1 a where not exists (select 'X' from temp2 b where b.col2 = a.col1);
    select 'X' 可以理解成存在(exists)不存在(not exists)的含义。
    如上面   找到a表中  col1的字段值不与b表中col2字段值相等的数据
    从效率来看:
    1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ;
    T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。
    2) select * from T1 where T1.a in (select T2.a from T2) ;
    T1数据量非常大而T2数据量小时,T1>>T2 时,2) 的查询效率高。
    简而言之,一般式:外表大,用IN;内表大,用EXISTS。
    执行方式:
    通过使用EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。oracle在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。
    in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询
    not exists:做NL,对子查询先查,有个虚表,有确定值,所以就算子查询有NULL最终也有值返回
    not in:做hash,对子查询表建立内存数组,用外表匹配,那子查询要是有NULL那外表没的匹配最终无值返回。

    一直以来认为exists比in效率高的说法是不准确的。
    如果查询的两个表大小相当,那么用in和exists差别不大。
    如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
    例如:表A(小表),表B(大表)
    1:
    select * from A where cc in (select cc from B)
    效率低,用到了A表上cc列的索引;
    select * from A where exists(select cc from B where cc=A.cc)
    效率高,用到了B表上cc列的索引。
    相反的
    2:
    select * from B where cc in (select cc from A)
    效率高,用到了B表上cc列的索引;
    select * from B where exists(select cc from A where cc=B.cc)
    效率低,用到了A表上cc列的索引。
    not in 和not exists
    如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
    而not extsts 的子查询依然能用到表上的索引。
    所以无论那个表大,用not exists都比not in要快。
    一直听到的都是说尽量用exists不要用in,因为exists只判断存在而in需要对比值,所以exists比较快,但看了看网上的一些东西才发现根本不是这么回事。
    Select * from T1 where x in ( select y from T2 )
    执行的过程相当于:
    select *
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;

        1
        2
        3

    select * from t1 where exists ( select null from t2 where y = x )
    执行的过程相当于:
    for x in ( select * from t1 )
       loop
          if ( exists ( select null from t2 where y = x.x )
          then
             OUTPUT THE RECORD
          end if
    end loop

        1
        2
        3
        4
        5
        6
        7
    in的方式比较直观,exists则有些绕,而且in可以用于各种子查询,而exists好像只用于关联子查询(其他子查询当然也可以用,可惜没意义)。
    由于exists是用loop的方式,所以,循环的次数对于exists影响最大,所以,外表要记录数少,内表就无所谓了,
    而in用的是hash join,
    所以内表如果小,整个查询的范围都会很小,
    如果内表很大,外表如果也很大就很慢了,
    这时候exists才真正的会快过in的方式。
    not in 和not exists
    如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;
    而not extsts 的子查询依然能用到表上的索引。
    所以无论那个表大,用not exists都比not in要快。
    也就是说,in和exists需要具体情况具体分析
    not in和not exists就不用分析了,尽量用not exists就好了。


    典型的连接类型共有3种:
    排序 - - 合并连接(Sort Merge Join (SMJ) )
    嵌套循环(Nested Loops (NL) )
    哈希连接(Hash Join)
    嵌套循环和哈希连接的算法还是有不同,在理论上哈希连接要快过排序和nl,当然实际情况比理论上有复杂的多,不过两者还是有差异的.
    1 关联子查询与非关联子查询
    关联子查询需要在内部引用外部表,而非关联子查询不要引用外部表。
    对于父查询中处理的记录来说,一个关联子查询是每行计算一次,
    然而一个非关联子查询只会执行一次,而且结果集被保存在内存中(如果结果集比较小),
    或者放在一张oracle临时数据段中(如果结果集比较大)。
    一个“标量”子查询是一个非关联子查询,返回唯一记录。
    如果子查询仅仅返回一个记录,那么oracle优化器会将结果缩减为一个常量,
    而且这个子查询只会执行一次。
    select from emp where deptno in (select deptno from dept where dept_name=’admin’);
    2.如何选择?
    根据外部查询,以及子查询本身所返回的记录的数目。如果两种查询返回的结果是相同的,哪一个效率更好?
    关联子查询的系统开销:对于返回到外层查询的记录来说,子查询会每次执行一次。因此,必须保证任何可能的时候子查询都要使用索引。
    非关联子查询的系统开销:子查询只会执行一次,而且结果集通常是排好序的,并保存在临时数据段中,其中每一个记录在返回时都会被父级查询引用,在子查询返回大量记录的情况下,将这些结果集排序回增大系统的开销。
    所以:如果父查询只返回较少的记录,那么再次执行子查询的开销不会非常大,如果返回很多数据行,那么直查询就会执行很多次。 如果子查询返回较少的记录,那么为内存中保存父查询的结果集的系统开销不会非常大,如果子查询返回多行,那么需要将结果放在临时段上,然后对数据段排序,以便为负查询中的每个记录服务。
    3结论:
        1)在使用一个关联子查询是,使用in 或者 exists子句的子查询执行计划通常都相同
        2)exists子句通常不适于子查询
        3)在外部查询返回相对较少记录时,关联子查询比非关联子查询执行得要更快。
        4)如果子查询中只有少量的记录,则非关联子查询会比关联子查询执行得更快。

    备注:随笔中内容来源于网上资料整理,仅供参考。

  • 相关阅读:
    MVVM架构~knockoutjs系列之表单添加(验证)与列表操作源码开放
    MVVM架构~knockoutjs系列之验证成功提示显示
    MVVM架构~knockoutjs系列之正则表达式使规则更灵活
    郁闷~win7无法进行局域网访问解决
    不合规范的html段落php处理细则
    备份一个通过拷贝来创建虚拟机镜像的脚本
    [置顶] ffmpg简介以及用它实现音频视频合并(java)
    [Java] HttpClient有个古怪的stalecheck选项
    POJ 1260 Pearls
    “AIR SDK 0.0: AIR SDK location “...devsdksAIRSDKWin” does not exist.”问题解决~
  • 原文地址:https://www.cnblogs.com/Alanf/p/7412460.html
Copyright © 2011-2022 走看看