網上相關資訊很多很多,到底not in 與 not exists誰的效率高,說實話,我也不知道!
select count(1) from ba_ry_jbxx a where not exists (select b.gmsfzh from ba_ry_zgkssh b where a.gmsfzh = b.gmsfzh);
select count(1) from ba_ry_jbxx a where a.gmsfzh not in (select b.gmsfzh from ba_ry_zgkssh b );
以下針對這兩條語句分析:
說到比較,首先得有共同點才會去比較,共同點就是:都可以查詢a表中的gmsfzh字段的值不在b表中的gmsfzh字段裡的記錄數。
前提條件是首先得保證這兩個語句查詢的資料的正确性,才可以進行效率的比較。
(1)當b表中的gmsfzh字段有空值時,用not in查詢結果為0.是以這兩個語句比較效率就沒有任何意義了!就直接用not exists!
(2)當a表中的gmsfzh字段有空值時,查詢結果固然也不一樣,用 not exists 查詢的記錄數會大于用not in的記錄數,因為 not exists把空值也
作為查詢結果了,而not in不把空值作為結果。
(
至于為什麼,我的了解是:因為not exists會關聯a.gmsfzh = b.gmsfzh一下,除了關聯上的資料其他的在a表中剩下的記錄都認為不在b表中,因為空值肯定是關聯不上的,
是以就認為空值不在b表中。
而為什麼用not in時,a表中的空值就不算在查詢結果内呢!因為oracle就這麼規定的)
是以當a表中的gmsfzh字段有空值時,因為查詢結果都不一樣,你覺得哪個查詢結果是正确的,固然就用哪個!
如果排除兩個表的空值的問題,或者說a表中的空值并不影響查詢結果的正确性時,接下來可以考慮not in 和not exists的執行效率問題了:
資料量情況:a表 100條記錄, b表 70000條記錄,執行以下兩語句:
select count(1) from ba_ry_jbxx a where not exists (select b.gmsfzh from ba_ry_zgkssh b where a.gmsfzh = b.gmsfzh);
select count(1) from ba_ry_jbxx a where a.gmsfzh not in (select b.gmsfzh from ba_ry_zgkssh b );
當兩個表都為gmsfzh字段建了索引的情況下
實測結果如下:
用not exists,耗時0.015秒。
用not in,耗時50.641秒。
這差距還真有點大。。。
毫無疑問,用not exists走索引了,而not in 并不走索引。
當删除兩個表的索引之後:
實測結果如下:
用not exists,耗時50秒。
用not in,耗時 50.875秒,此時not exists和not in 幾乎差不多。
資料量不變,反過來測試:
select count(1) from ba_ry_zgkssh b where not exists (select a.gmsfzh from ba_ry_jbxx a where b.gmsfzh = a.gmsfzh);
select count(1) from ba_ry_zgkssh b where b.gmsfzh not in (select a.gmsfzh from ba_ry_jbxx a );
無索引:
用not in,耗時 3.703秒.
用not exists,耗時3.641秒。(此時至少說明,無索引的情況下,b表資料量遠遠大于a表時,not in與not exists效率差不多)
建完索引後:
用not in,耗時 3.937秒.
用not exists,耗時0.813秒。
以上資料測試可見,索引的重要性。
我總覺得,not in既然存在,肯定有他存在的道理。
測試這麼多,至少證明,有索引的情況下,多數時候not exists完虐not in的執行效率。
現在我糾結的問題就是,到底什麼情況下not in效率要高于not exists? 還請高人留言指點一下。