MySQL中in和exists區(qū)別詳解
一、提前準(zhǔn)備
為了大家學(xué)習(xí)方便,我在這里面建立兩張表并為其添加一些數(shù)據(jù)。
一張水果表,一張供應(yīng)商表。
水果表 fruits表
| f_id | f_name | f_price |
|---|---|---|
| a1 | apple | 5 |
| a2 | appricot | 2 |
| b1 | blackberry | 10 |
| b2 | berry | 8 |
| c1 | cocount | 9 |
供應(yīng)商表 suppliers表
| s_id | s_name |
|---|---|
| 101 | 天虹 |
| 102 | 沃爾瑪 |
| 103 | 家樂福 |
| 104 | 華潤(rùn)萬家 |
我們將用這兩張表做演示。
二、什么是exists
exists關(guān)鍵字后面的參數(shù)是一個(gè)任意的子查詢,系統(tǒng)對(duì)子查詢進(jìn)行運(yùn)算以判斷它是否返回行,如果至少返回一行,那么exists的結(jié)果為true ,此時(shí)外層的查詢語句將進(jìn)行查詢;如果子查詢沒有返回任何行,那么exists的結(jié)果為false,此時(shí)外層語句將不進(jìn)行查詢。
需要注意的是,當(dāng)我們的子查詢?yōu)?SELECT NULL 時(shí),MYSQL仍然認(rèn)為它是True。


三、什么是in
in 關(guān)鍵字進(jìn)行子查詢時(shí),內(nèi)層查詢語句僅僅返回一個(gè)數(shù)據(jù)列,這個(gè)數(shù)據(jù)列的值將提供給外層查詢語句進(jìn)行比較操作。
為了測(cè)試in 關(guān)鍵字,我在水果表中加了s_id一列
水果表 fruits表
| f_id | f_name | f_price | s_id |
|---|---|---|---|
| a1 | apple | 5 | 101 |
| a2 | appricot | 2 | 103 |
| b1 | blackberry | 10 | 102 |
| b2 | berry | 8 | 104 |
| c1 | cocount | 9 | 103 |

四、exists和in
in和exists到底有啥區(qū)別那,要什么時(shí)候用in,什么時(shí)候用exists?
我們先記住口訣再說細(xì)節(jié)!“外層查詢表小于子查詢表,則用exists,外層查詢表大于子查詢表,則用in,如果外層和子查詢表差不多,則愛用哪個(gè)用哪個(gè)。”
我想你已經(jīng)看出來了,當(dāng)fruits表數(shù)據(jù)很大的時(shí)候不適合用in,因?yàn)樗疃鄷?huì)將fruits表數(shù)據(jù)全部遍歷一次。
如:suppliers表有10000條記錄,fruits表有1000000條記錄,那么最多有可能遍歷10000*1000000次,效率很差。
再如:suppliers表有10000條記錄,fruits表有100條記錄,那么最多有可能遍歷10000*100次,遍歷次數(shù)大大減少,效率大大提升。
但是:suppliers表有10000條記錄,fruits表有100條記錄,那么exists()還是執(zhí)行10000次,還不如使用in()遍歷10000*100次,因?yàn)閕n()是在內(nèi)存里遍歷,而exists()需要查詢數(shù)據(jù)庫,我們都知道查詢數(shù)據(jù)庫所消耗的性能更高,而內(nèi)存比較很快。
因此我們只需要記住口訣:“外層查詢表小于子查詢表,則用exists,外層查詢表大于子查詢表,則用in,如果外層和子查詢表差不多,則愛用哪個(gè)用哪個(gè)?!?/p>
五、not exists和not in

和exists一樣,用到了suppliers上的id索引,exists()執(zhí)行次數(shù)為fruits.length,不緩存exists()的結(jié)果集。

因?yàn)閚ot in實(shí)質(zhì)上等于!= and != ···,因?yàn)?=不會(huì)使用索引,故not in不會(huì)使用索引。
為啥not in不會(huì)使用索引?
我們假設(shè)有100萬數(shù)據(jù),s_id只有0和1兩個(gè)值,利用索引我們要先讀索引文件,然后二分查找,找到對(duì)應(yīng)的數(shù)據(jù)磁盤指針,再根據(jù)讀到的指針在磁盤上對(duì)應(yīng)的數(shù)據(jù),影響結(jié)果集50萬,這種情況,和直接全表掃描哪個(gè)快顯而易見。
如果你s_id字段是一個(gè)unique,就會(huì)用到索引。
如果你一定要用索引,可以用force index,不過效率不會(huì)有改善一般還會(huì)更慢就是了。
合理使用索引,Cardinality是一個(gè)重要指標(biāo),太小的話跟沒建沒區(qū)別,還浪費(fèi)空間。
因此,不管suppliers和fruits大小如何,均使用not exists效率會(huì)更高。
到此這篇關(guān)于MySQL中in和exists區(qū)別詳解的文章就介紹到這了,更多相關(guān)MySQL in和exists區(qū)別內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信