exists 的自由之路

解释与比较:

        in 语句:

                      只执行一次,确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积(翻译:笛卡尔乘积是指在数学中,两个集合XY的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。),然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。

例:

    select a.* from  dual a where a.dummy in (select b.dummy from dual b);

执行流程:

      首先会执行from语句找出dual表中的数据,然后执行 in 里面的子查询,再然后将查询到的结果和原有的dual表做一个笛卡尔积,再根据我们的a.dummy IN b.dummy 的条件,将结果进行筛选(既比较dummy 列的值是否相等,将不相等的删除)。最后,得到符合条件的数据。

 

EXISTS语句:

                      执行dual.length次,指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。

     例:

          select a.* from  dual a where exists (select * from dual b where a.dummy = b.dummy);

 

执行流程:

              首先,我们先查询的不是子查询的内容,而是查我们的主查询的表(select a.* from dual),然后,根据表的每一条记录,执行以下语句(exists (select * from dual b where a.dummy = b.dummy)),依次去判断where后面的条件是否成立,如果成立则返回true不成立则返回false。如果返回的是true的话,则该行结果保留,如果返回的是false的话,则删除该行,最后将得到的结果返回。

区别及应用场景:

     in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理。

    in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。
 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章