mysql in和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條件 

 

 

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);

而exists就沒有這個限制

 

 

IN查詢在內部表和外部表上都可以使用到索引; Exists查詢僅在內部表上可以使用到索引;當子查詢結果集很大,而外部表較小的時候,Exists的Block Nested Loop(Block 嵌套循環)的作用開始顯現,並彌補外部表無法用到索引的缺陷,查詢效率會優於IN。當子查詢結果集較小,而外部表很大的時候,Exists的Block嵌套循環優化效果不明顯,IN 的外表索引優勢佔主要作用,此時IN的查詢效率會優於Exists。 網上的說法不準確。其實“表的規模”不是看內部表和外部表,而是外部表和子查詢結果集

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章