mysql中 = 與in區別_淺析mysql中 exists 與 in 的區別,空判斷


1、exists的使用

exists對外表用loop逐條查詢,每次查詢都會查看exists的條件語句,當exists里的條件語句能夠返回記錄行時(無論記錄行是的多少,只要能返回),條件就為真,返回當前loop到的這條記錄;

反之如果exists里的條件語句不能返回記錄行,則當前loop到的這條記錄被丟棄,exists的條件就像一個bool條件,當能返回結果集則為true,不能返回結果集則為 false。

如下:

select * from user where exists (select 1);

對user表的記錄逐條取出,由於子條件中的select 1永遠能返回記錄行,那么user表的所有記錄都將被加入結果集,所以與 select * from user;是一樣的。

如下:

select * from user where exists (select * from user where userId = 0);

可以知道對user表進行loop時,檢查條件語句(select * from user where userId = 0),由於userId永遠不為0,所以條件語句永遠返回空集,條件永遠為false,那么user表的所有記錄都將被丟棄。

not exists與exists相反,也就是當exists條件有結果集返回時,loop到的記錄將被丟棄,否則將loop到的記錄加入結果集。

總的來說,如果A表有n條記錄,那么exists查詢就是將這n條記錄逐條取出,然后判斷n遍exists條件 。

2、in 的使用

in查詢相當於多個or條件的疊加,這個比較好理解,比如下面的查詢:

select * from user where userId in (1, 2, 3);

等效於

select * from user where userId = 1 or userId = 2 or userId = 3;

not in 與 in相反,如下

select * from user where userId not in (1, 2, 3);

等效於

select * from user where userId != 1 and userId != 2 and userId != 3;

總的來說,in查詢就是先將子查詢條件的記錄全都查出來,假設結果集為B,共有m條記錄,然后再將子查詢條件的結果集分解成m個,再進行m次查詢。

值得一提的是,in查詢的子條件返回結果必須只有一個字段,例如:

select * from user where userId in (select id from B);

而不能是

select * from user where userId in (select id, age from B);

3.1、exists 與 in 的比較

下面來考慮exists和in的性能,考慮如下SQL語句。

前提條件:表A(小表),表B(大表)。

查詢1:

select * from A where exists (select * from B where B.id = A.id);

查詢2:

select * from A where A.id in (select id from B);

以上查詢使用了in語句,in()只執行一次,它查出B表中的所有id字段並緩存起來。之后檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有記錄。

可以看出,當B表數據較大時不適合使用in(),因為它會B表數據全部遍歷一次。

如:A表有10000條記錄,B表有1000000條記錄,那么最多有可能遍歷10000*1000000次,效率很差。

再如:A表有10000條記錄,B表有100條記錄,那么最多有可能遍歷10000*100次,遍歷次數大大減少,效率大大提升。

以上查詢使用了exists語句,exists()會執行A.length次,它並不緩存exists()結果集,因為exists()結果集的內容並不重要;重要的是結果集中是否有記錄,如果有則返回true,沒有則返回false。

當B表比A表數據大時適合使用exists(),因為它沒有那么多的遍歷操作,只需要再執行一次查詢就行。

如:A表有10000條記錄,B表有1000000條記錄,那么exists()會執行10000次去判斷A表中的id是否與B表中的id相等。

如:A表有10000條記錄,B表有100000000條記錄,那么exists()還是執行10000次,因為它只執行A.length次,可見B表數據越多,越適合exists()發揮效果。

再如:A表有10000條記錄,B表有100條記錄,那么exists()還是執行10000次,還不如使用in()遍歷10000*100次,因為in()是在內存里遍歷比較,而exists()需要查詢數據庫,我們都知道查詢數據庫所消耗的性能更高,而內存比較很快。

3.2、not exists 與 not in比較

查詢1:

select * from A where not exists (select * from B where B.id = A.id);

查詢2:

select * from A where A.id not in (select id from B);

not in是個范圍查詢,這種!=的范圍查詢無法使用任何索引,那么內外表都進行全表掃描,沒有用到索引;

而not extsts 的子查詢依然能用到表上的索引;

所以無論那個表大,用not exists都比not in要快

3.3、in 與 = 的區別

select name from student where name in ('zhang','wang','li','zhao');

select name from student where name='zhang' or name='li' or name='wang' or name='zhao' ;

的結果是相同的。

4.空判斷 is null、is not null

總結:

如果查詢的兩個表大小相當,那么用in和exists差別不大。

如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in。

mysql中的in語句是把外表和內表作hash 連接,而exists語句是對外表作loop循環,每次loop循環再對內表進行查詢。一直大家都認為exists比in語句的效率要高,這種說法其實是不准確的。這個是要區分環境的。


————————————————
版權聲明:本文為CSDN博主「科材」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_29959015/article/details/113331554


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM