天天看點

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

前面我們學習了NOT EXISTS和NOT IN的比較,當然少不了EXISTS和IN的比較,是以本節我們來學習EXISTS和IN的比較,簡短的内容,深入的了解,Always to review the basics。

我們建立表Table1并且取出前面建立BigTable表中的六條資料并插入其中,同時有一條資料重複,如下:

此時我們來進行IN查詢

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

我們在之前講過若是内部聯接中此時會傳回六條資料,因為内部聯接着重強調的是JOIN後面的表,若右表有多條資料比對上,此時則會傳回多條資料,但是在IN查詢中,此時隻會傳回五條資料,為何如此呢?

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

此時用IN查詢時即使在子查詢中有重複資料時也不會擔心出問題,它會自動進行過濾處理,因為在上圖中利用了Semi Join半聯接中右半聯接或左半聯接,也就是說隻傳回重複的資料中的一條。那麼在EXISTS中情況又是怎樣呢?

此時因為沒有WHERE條件,此時會傳回外部查詢表中所有資料,為了和上述IN查詢實作等同的結果,我們需要加上WHERE條件

而EXISTS相對于IN來說當需要比較兩個或兩個以上條件時,EXISTS能更好的實作而IN就沒那麼容易了,比如如下

好了,到了這裡我們開始講講二者性能問題

我們直接利用前面的表來進行查詢

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

二者都是利用預設的聚集索引掃描和哈希比對中的右半聯接且開銷一緻。接下來我們再來在二者查詢列上建立索引

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

此時隻是建立了索引後查詢效率改善了,而且查詢計劃較之前隻是哈希比對中的左半聯接替換成了合并聯接中的内部聯接,同時增加了流聚合。二者在開銷上仍是一緻的。在我所看其他教程中印象中一直都在說利用EXISTS代替IN,其EXISTS查詢性能高于IN,而且事實卻是開銷一緻,難道是100萬資料太小,還是場景不夠,還是語句不夠複雜麼。都在說看使用場景,那麼到底是在什麼場景下EXISTS比IN性能好呢,對此有更深入了解的你們,希望在評論中得到最實際的回答。而我認為覺得用EXISTS的話,隻是EXISTS比IN更加靈活而已,而且不會出現意外的結果。下面我們繼續往下看。

我們接下來看看用IN會出現什麼意外的情況,我們首先建立測試表,并插入資料如下:

插入測試資料

table1和table2中的資料分别如下:

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言
SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

我們來對比EXISTS和IN查詢,如下:

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

此時二者傳回的結果都是正确,接下來我們再來看其他情況,我們需要擷取所有table1中資料沒有在table2中的所有行。

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

此時利用EXISTS得到了正确的結果,而通過IN查詢未達到我們查詢的目的,原因之前也有說過IN是基于三值邏輯,此時遇到NULL則會當做UNKNOWN來處理,是以最終得到的結果集是錯誤的。我們繼續往下探讨。

我們重新建立測試表并插入測試資料,如下:

我們首先進行如下查詢:

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

此時結果是正确的,假如在子查詢中我們将列id2寫成了id1,那麼情況又會是怎樣的呢?

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

不知你是否注意到什麼沒有,表面是沒什麼問題,我們接着運作下上述子查詢

SQL Server-聚焦EXISTS AND IN性能分析(十六)前言

單獨運作查詢時,結果居然出錯了,到這了我們再看下建立的表的列,id1是在Table1中而非在Table2中,是以導緻了這種意外的錯誤,如果手寫錯誤,結果資料也有,一般是不會覺察不到,通過使用IN查詢就導緻了意外的出現。而如下利用EXISTS時會直接報錯,而不是得到錯誤的結果集

當然了也有人會說根本不會犯這樣低級錯誤,但是誰能保證呢,SQL有智能提示更加容易犯這樣的錯誤,因為直接在子查詢就會有這樣的列出現,但是該列在子查詢表中根本不存在。是以基于探讨的兩點,利用EXISTS更加保險。到此,關于EXISTS和IN的介紹算是結束,下此結論。

EXISTS和IN性能分析結論:我們推薦使用EXISTS,而不是IN,原因不是EXISTS性能優于IN,二者性能開銷是一樣的,而是利用EXISTS比IN更加靈活,更加安全、保險不會出現意想不到的結果。

本節我們講解了EXISTS和IN,關于其二者在性能方面還是有點疑惑,畢竟場景不夠,當然最後還是推薦使用EXISTS,而原因不在于性能。我們下節講解LEFT JOIN和NOT EXISTS,簡短的内容,深入的了解,我們下節再會。