in与exist , not in与not exist 的区别

  • Post author:
  • Post category:其他




  1. in


    和exists



  2. in


    是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比


    in


    效率高的说法是不准确的。


  3. 如果查询的两个表大小相当,那么用

    in


    和exists差别不大。


  4. 如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用

    in





  5. 例如:表A(小表),表B(大表)1:

    select


    *


    from


    A


    where


    cc


    in


    (


    select


    cc


    from


    B)


  6. 效率低,用到了A表上cc列的索引;

    select


    *


    from


    A


    where


    exists(


    select


    cc


    from


    B


    where


    cc=A.cc)


  7. 效率高,用到了B表上cc列的索引。

  8. 相反的2:

    select


    *


    from


    B


    where


    cc


    in


    (


    select


    cc


    from


    A)


  9. 效率高,用到了B表上cc列的索引;

    select


    *


    from


    B


    where


    exists(


    select


    cc


    from


    A


    where


    cc=B.cc)


  10. 效率低,用到了A表上cc列的索引。




  11. not




    in





    not


    exists



  12. 如果查询语句使用了

    not




    in


    那么内外表都进行全表扫描,没有用到索引;而


    not


    extsts 的子查询依然能用到表上的索引。所以无论那个表大,用


    not


    exists都比


    not




    in


    要快。






  13. not




    in


    逻辑上不完全等同于


    not


    exists,如果你误用了


    not




    in


    ,小心你的程序存在致命的BUG:



  14. 请看下面的例子:


  15. create




    table


    t1 (c1 number,c2 number);



  16. create




    table


    t2 (c1 number,c2 number);




  17. insert




    into


    t1


    values


    (1,2);



  18. insert




    into


    t1


    values


    (1,3);



  19. insert




    into


    t2


    values


    (1,2);



  20. insert




    into


    t2


    values


    (1,


    null


    );




  21. select


    *


    from


    t1


    where


    c2


    not




    in


    (


    select


    c2


    from


    t2);



  22. no




    rows


    found



  23. select


    *


    from


    t1


    where




    not


    exists (


    select


    1


    from


    t2


    where


    t1.c2=t2.c2);


  24. c1 c2

  25. 1 3


  26. 正如所看到的,

    not




    in


    出现了不期望的结果集,存在逻辑错误。如果看一下上述两个


    select


    语句的执行计划,也会不同。后者使用了hash_aj。


  27. 因此,请尽量不要使用

    not




    in


    (它会调用子查询),而尽量使用


    not


    exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录,正如上面例子所示。


  28. 除非子查询字段有非空限制,这时可以使用

    not




    in


    ,并且也可以通过提示让它使用hasg_aj或merge_aj连接