只要百度not in和not exists,清一色的not exists的效率優於not in,畢竟not exists只是去強調是否返回結果集,只是一個bool值,而not in是返回一個結果集,是由大量大量數據構成的。所以一開始我在做的時候寫的是not in,然后前輩告訴我效率太低,改成了not exists,結果查詢速度特別慢。為什么呢?首先來看看sql語句,本身sql語句特別長,只寫出where條件中的not in和not exists篩選部分語句。
not in: where substr(表A.字段A,1,9) not in (select substr(字段B,1,9) from 表B) and 表A.字段C not in (select 字段D from 表C)
not exists:where not exists (select 1 from 表B where substr(表B.字段B,1,9) = substr(表A.字段A,1,9) and not exists (select 1 from 表C where 表C.字段D = 表A.字段C)
主表是表A,大概也就不超過10萬的數據量吧,然后前面表A先做過一次inner join和兩次left join,inner join排除了表A中將近六分之五的數據,兩次left join中一次是替換掉表A中的某個字段的值,另一次多取一次值。這些處理都花極其少的時間。然后現在這么做遠遠不夠,表A還要根據另外兩張表中的數據來進行再次過濾。這個行為就是通過兩個not in來完成的。一開始借鑒了前輩的提議,用了not exists,畢竟返回一個bool值是大量的節省時間,然后實際結果下來卻花了整整3秒多,這對於一個用戶來是完完全全不能接受的。為什么原因呢?最后推導出原因肯定是在前一句not exists中的兩個substr。表B中大概只有5000不到的數據,然而表A里面卻有幾萬條數據,用表B中的每個值和表A中的每個值都要進行一次比較處理,那會是多么一個龐大的處理!!盡管not exists只是返回一個bool值,但是卻忽略了里面select語句中where的處理量,而且還要進行一次substr處理。一開始沒有想到再去用not in處理,先想到的用的是視圖,因為想去除掉一次substr處理,提前把表A中的數據處理好放到視圖里,然后再進行處理。結果更加令人意外,視圖更加慢,而且還取不到正確結果。這部分的原因我猜應該是表A里面有兩個主鍵,而我做視圖的過程中只取了其中一個主鍵,但是這個取出的這個主鍵是受后面那個主鍵約束的,創建了垃圾數據比較多的視圖。(其實我本來也不太會視圖,還是前輩教的= =。。)我抱着破罐子破摔的想法把not exists換成了not in,然后奇跡出現了,取完整個數據0.1秒一下級別的,反正一眨眼的時間。。完美的符合了系統不管什么處理都不能超過3秒的要求。。
為什么not in在這種情況下效率遠遠高於not exists呢?按我一介菜鳥的理解,not exists里面的where處理拖慢了整個速度,況且這次處理本來就是想要返回結果集,況且在這之前已經拿了表A.字段A,最終正確的數據是根據這個字段A來獲取的,只要拿出不與從其它兩張表不匹配的數據即可,就相當於整理衣櫃,把沒用的衣服拿出來這一個過程而已。而且字段A,B,C,D都是各個表的主鍵,不存在null值這種概念,沒有必要進行額外的判斷。所以最后not in的速度比not exists整整快了3秒有余。
數據庫是DB2(不要吐槽,日企就是這么喜歡IBM,頂層終於考慮要換oracle。。。)
一介菜鳥,寫的錯誤的地方,歡迎大神提意見,謝謝~~