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效率高的說法是不準確的。
 

 

 

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