MYSQL中的in茵乱、not in、exists及not exists的區(qū)別

一孟岛、in和exists

in是把外表和內(nèi)表作hash連接瓶竭,而exists是對外表作loop循環(huán),每次loop循環(huán)再對內(nèi)表進(jìn)行查詢蚀苛,一直以來認(rèn)為exists比in效率高的說法是不準(zhǔn)確的在验。如果查詢的兩個表大小相當(dāng),那么用in和exists差別不大堵未;如果兩個表中一個較小一個較大腋舌,則子查詢表大的用exists,子查詢表小的用in渗蟹。

例如:表A(小表)块饺,表B(大表)

select * from A where cc in(select cc from B)                 -->效率低赞辩,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc)  -->效率高授艰,用到了B表上cc列的索引;

相反的:

select * from B where cc in(select cc from A)                 -->效率高辨嗽,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc)  -->效率低,用到了A表上cc列的索引;

二淮腾、not in和not exists

not in邏輯上不完全等同于not exists糟需,如果你誤用了not in,小心你的程序存在致命的BUG谷朝,請看下面的例子:

create table t1(c1 int,c2 int);
create table t2(c1 int,c2 int);
insert into t1 values(1,2);
insert into t1 values(1,3);
insert into t2 values(1,2);
insert into t2 values(1,null);
select * from t1 where c2 not in (select c2 from t2);                   -->執(zhí)行結(jié)果:無
select * from t1 where not exists (select 1 from t2 where t2.c2=t1.c2)  -->執(zhí)行結(jié)果:1 3

正如所看到的洲押,not in出現(xiàn)了不期望的結(jié)果集,存在邏輯錯誤圆凰。如果看一下上述兩個select 語句的執(zhí)行計劃杈帐,也會不同,后者使用了hash_aj专钉,所以挑童,請盡量不要使用not in(它會調(diào)用子查詢),而盡量使用not exists(它會調(diào)用關(guān)聯(lián)子查詢)跃须。使用not in如果子查詢中返回的任意一條記錄含有空值站叼,則查詢將不返回任何記錄。如果子查詢字段有非空限制回怜,這時可以使用not in大年,并且可以通過提示讓它用hasg_aj或merge_aj連接。

如果查詢語句使用了not in玉雾,那么對內(nèi)外表都進(jìn)行全表掃描,沒有用到索引轻要;而not exists的子查詢依然能用到表上的索引复旬。所以無論哪個表大,用not exists都比not in要快冲泥。

三驹碍、in與=的區(qū)別

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

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

結(jié)果是相同的。

四凡恍、關(guān)于EXISTS:

EXISTS用于檢查子查詢是否至少會返回一行數(shù)據(jù)志秃,該子查詢實際上并不返回任何數(shù)據(jù),而是返回值True或False嚼酝。

EXISTS 指定一個子查詢浮还,檢測行的存在。

語法: EXISTS subquery

參數(shù): subquery 是一個受限的 SELECT 語句 (不允許有 COMPUTE 子句和 INTO 關(guān)鍵字)闽巩。

結(jié)果類型: Boolean 如果子查詢包含行钧舌,則返回 TRUE 担汤,否則返回 FLASE 。

結(jié)論:

select * from A where exists (select 1 from B where A.id=B.id)
EXISTS(包括 NOT EXISTS )子句的返回值是一個boolean值洼冻。 EXISTS內(nèi)部有一個子查詢語句(SELECT ... FROM...),我將其稱為EXIST的內(nèi)查詢語句崭歧。其內(nèi)查詢語句返回一個結(jié)果集, EXISTS子句根據(jù)其內(nèi)查詢語句的結(jié)果集空或者非空,返回一個布爾值撞牢。

一種通俗的可以理解為:將外查詢表的每一行率碾,代入內(nèi)查詢作為檢驗,如果內(nèi)查詢返回的結(jié)果取非空值屋彪,則EXISTS子句返回TRUE所宰,這一行行可作為外查詢的結(jié)果行,否則不能作為結(jié)果撼班。

分析器會先看語句的第一個詞歧匈,當(dāng)它發(fā)現(xiàn)第一個詞是SELECT關(guān)鍵字的時候,它會跳到FROM關(guān)鍵字砰嘁,然后通過FROM關(guān)鍵字找到表名并把表裝入內(nèi)存件炉。接著是找WHERE關(guān)鍵字,如果找不到則返回到SELECT找字段解析矮湘,如果找到WHERE斟冕,則分析其中的條件,完成后再回到SELECT分析字段缅阳。最后形成一張我們要的虛表磕蛇。

WHERE關(guān)鍵字后面的是條件表達(dá)式。條件表達(dá)式計算完成后十办,會有一個返回值秀撇,即非0或0,非0即為真(true)向族,0即為假(false)呵燕。同理WHERE后面的條件也有一個返回值,真或假件相,來確定接下來執(zhí)不執(zhí)行SELECT再扭。

分析器先找到關(guān)鍵字SELECT,然后跳到FROM關(guān)鍵字將STUDENT表導(dǎo)入內(nèi)存夜矗,并通過指針找到第一條記錄泛范,接著找到WHERE關(guān)鍵字計算它的條件表達(dá)式,如果為真那么把這條記錄裝到一個虛表當(dāng)中紊撕,指針再指向下一條記錄罢荡。如果為假那么指針直接指向下一條記錄,而不進(jìn)行其它操作。一直檢索完整個表柠傍,并把檢索出來的虛擬表返回給用戶麸俘。EXISTS是條件表達(dá)式的一部分,它也有一個返回值(true或false)惧笛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末从媚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子患整,更是在濱河造成了極大的恐慌拜效,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件各谚,死亡現(xiàn)場離奇詭異紧憾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)昌渤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門赴穗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人膀息,你說我怎么就攤上這事般眉。” “怎么了潜支?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵甸赃,是天一觀的道長。 經(jīng)常有香客問我冗酿,道長埠对,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任裁替,我火速辦了婚禮项玛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弱判。我一直安慰自己稍计,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布裕循。 她就那樣靜靜地躺著,像睡著了一般净刮。 火紅的嫁衣襯著肌膚如雪剥哑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天淹父,我揣著相機(jī)與錄音株婴,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛困介,可吹牛的內(nèi)容都是我干的大审。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼座哩,長吁一口氣:“原來是場噩夢啊……” “哼徒扶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起根穷,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤姜骡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屿良,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體圈澈,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年尘惧,在試婚紗的時候發(fā)現(xiàn)自己被綠了康栈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡喷橙,死狀恐怖啥么,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情重慢,我是刑警寧澤饥臂,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站似踱,受9級特大地震影響隅熙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜核芽,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一囚戚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轧简,春花似錦驰坊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至皮璧,卻和暖如春舟扎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悴务。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工睹限, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓羡疗,卻偏偏與公主長得像染服,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叨恨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內(nèi)容