以前看過(guò)一次關(guān)于這兩的區(qū)別苫幢,但由于印象不深就忘了,最近想起來(lái)就補(bǔ)了下麻蹋,為了加深印象,就寫了 焊切。
exists和in
in 是把外表和內(nèi)表作hash join扮授,而exists是對(duì)外表作loop芳室,每次loop再對(duì)內(nèi)表進(jìn)行查詢。
如:
A:select * from t1 a where exists (select * from t2 b where b.id = a.id)
B:select * from t1 a where a.id in (select b.id from t2 b)
對(duì)于A刹勃,用到了t2上的id索引堪侯,exists執(zhí)行次數(shù)為t1.length,不緩存exists的結(jié)果集荔仁。
對(duì)于B伍宦,用到了t1上的id索引,首先執(zhí)行in語(yǔ)句乏梁,然后將結(jié)果緩存起來(lái)次洼,之后遍歷t1表,將滿足結(jié)果的加入結(jié)果集遇骑,所以執(zhí)行次數(shù)為t1.length*t2.length次卖毁。
因此對(duì)t1表大t2表小的情況使用in,t2表小t1表大的情況使用exists
not exists和not in
A:select * from t1 a where not exists (select * from t2 b where b.id = a.id)
B:select * from t1 a where a.id not in (select b.id from t2 b)
對(duì)于A质蕉,和exists一樣,用到了t2上的id索引翩肌,exists()執(zhí)行次數(shù)為t1.length模暗,不緩存exists()的結(jié)果集。
而對(duì)于B念祭,因?yàn)閚ot in實(shí)質(zhì)上等于!= and != ···
兑宇,因?yàn)?=不會(huì)使用索引,故not in不會(huì)使用索引粱坤。
因此隶糕,不管t1和t2大小如何,均使用not exists效率會(huì)更高站玄。