SQL查詢性能分析之(not in)、(and not)、()、(!=)性能比較
<:article class="article-content">
在與朋友討論查詢時引出了not in 與and not兩種踢出方法,相互的口舌之爭之后我決定動手來查查看,他們到底有什么區別,誰的執行效率更高,今后該如何選擇性能最優的查詢條件。由於本人能力有 限,肚子中的墨水有限,所以本文有什么錯誤之處還望各位前輩指出。
在使用sql中我們會有各種各樣的條件篩選,常見的就是要踢出一部分我們不需要的數據,在where后面的踢出方法常見的有 (not in / and not / <> / !=) 這四種方法,既然存在這樣四種方法,那么我們又該如果選擇最佳方法呢?下面我們就一起來測試下這四種篩選條件的執行效率。
為了測試數據,我建了一張零時表@index中有三個字段:ID ,iID, idate 。然后循環插入1000000條數據。建表的語句:
declare @index table(id int,t_id int,idate date) declare @id int,@iid int,@idate date set @id =1 set @iid=1000000 Set @idate = GETDATE() while(@id<1000000) begin insert into @index values(@id,@iid,@idate) set @id=@id+1 Set @iid =@iid-1 end
我們使用SET STATISTICS TIME ON ;SET STATISTICS TIME OFF來查看sql耗時,在執行前先清空緩存DBCC DROPCLEANBUFFERS;查詢語句如下:
SET STATISTICS TIME ON select * from @index where id not in (1) select * from @index where not id=1 select * from @index where id<>1 select * from @index where id!=1 SET STATISTICS TIME OFF
Execute下我們先看看sql執行計划:
從sql執行計划中我們看不到區別,表掃描的結果頁都一樣,這里就不一一列出了,如果你們又懷疑可以自己試試!然后我們在看看執行結果中message消息中,我們對耗時的查詢:
當我們后面跟的篩選條件只有一條時,not in 的查詢結果會有明顯的優勢,而其他的幾種查詢結果也都大同小異,not似乎耗時也稍稍多點。但是往往我們在做篩選的時候not in 后面的條件會不止一個,如果只有這么一個篩選是的不出什么結果的,那么我們就加大篩選的條件。
SET STATISTICS TIME ON select * from @index where id not in (1,10,30,33,59,66,77,100,10000) select * from @index where not id=1 and not id=10 and not id=30 and not id=33 and not id=59 and not id=66 and not id=77 and not id=100 and not id=10000 select * from @index where id<>1 and id<>10 and id<>30 and id<>33 and id<>59 and id<>66 and id<>77 and id<>100 and id<>10000 select * from @index where id!=1 and id!=10 and id!=30 and id!=33 and id!=59 and id!=66 and id!=77 and id!=100 and id!=10000 SET STATISTICS TIME OFF
看看執行計划:
執行計划仍然相同,我們去看看耗時查詢:
到這里我們已經清楚了這四種篩選方法各自的執行效率,不知道是不是由於我用的是表變量,對查詢結果造成了一定的影響,如果有興趣你們也可以試下,對於 sql查詢條件我們可以盡量選擇比較合適的方法來做,比較需要踢出的數據比較多我們就不可能去用后面的三種一個一個的踢出,本文demo中采用的數據量是 1000000條已經是比較大的數據量了,這里看到這四種篩選條件執行消耗的時間並沒有多少優勢。
由於本文使用的是表變量,並沒有對物理掃描,所以並不能保證在做物理查詢時一致!學術是需要嚴謹的論證的,不能因為片面的原因而得出結論,那么我下面就來用物理表的掃描來查看他們的執行性能。
建表的過程就不在贅述,我們直接來看看sql執行計划,依然是上面的查詢語句,不過要注意我本次使用的是物理表的查詢:
--------清空緩存 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE SET STATISTICS TIME ON select * from [index] where id not in (1,10,30,33,59,66,77,100,10000) select * from [index] where not id=1 and not id=10 and not id=30 and not id=33 and not id=59 and not id=66 and not id=77 and not id=100 and not id=10000 select * from [index] where id<>1 and id<>10 and id<>30 and id<>33 and id<>59 and id<>66 and id<>77 and id<>100 and id<>10000 select * from [index] where id!=1 and id!=10 and id!=30 and id!=33 and id!=59 and id!=66 and id!=77 and id!=100 and id!=10000 SET STATISTICS TIME OFF
看看執行計划:
看看耗時查詢結果:
程序是一門嚴謹的科學,很多事情都需要我們自己去做去了解,我曾不止一次看到有很多文章寫道not in 在查詢的時候對內存消耗嚴重,性能低下,在數據達到百萬級別的時候查詢會很慢,但是當數據量大的時候任何查詢都會很慢的,既然sql中給我們提供了這些方 法,自有他的用武之地,而不能片面的覺得誰比誰更好,我們要根據需求選擇,最終的目的是為了解決問題,給世界創造價值。
由於本人能力有限,文中有錯誤之處還望給我前輩不吝賜教!