1. 程式人生 > >mysql中in與exists效率比較

mysql中in與exists效率比較

這條語句適用於a表比b表大的情況

select * from ecs_goods a where cat_id in(select cat_id from ecs_category);

這條語句適用於b表比a表大的情況
select * from ecs_goods a where EXISTS(select cat_id from ecs_category b where a.cat_id = b.cat_id);

原因:(轉發)

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

以上查詢使用了in語句,in()只執行一次,它查出B表中的所有id欄位並快取起來.之後,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有記錄.
它的查詢過程類似於以下過程

List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);

for(int i=0;i<A.length;i++) {
   for(int j=0;j<B.length;j++) {
      if(A[i].id==B[j].id) {
         resultSet.add(A[i]);
         break;
      }
   }
}
return resultSet;

可以看出,當B表資料較大時不適合使用in(),因為它會B表資料全部遍歷一次.
如:A表有10000條記錄,B表有1000000條記錄,那麼最多有可能遍歷10000*1000000次,效率很差.
再如:A表有10000條記錄,B表有100條記錄,那麼最多有可能遍歷10000*100次,遍歷次數大大減少,效率大大提升.

結論:in()適合B表比A表資料小的情況

select a.* from A a 
where exists(select 1 from B b where a.id=b.id)

以上查詢使用了exists語句,exists()會執行A.length次,它並不快取exists()結果集,因為exists()結果集的內容並不重要,重要的是結果集中是否有記錄,如果有則返回true,沒有則返回false.
它的查詢過程類似於以下過程

List resultSet=[];
Array A=(select * from A)

for(int i=0;i<A.length;i++) {
   if(exists(A[i].id) {    //執行select 1 from B b where b.id=a.id是否有記錄返回
       resultSet.add(A[i]);
   }
}
return resultSet;

當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()需要查詢資料庫,我們都知道查詢資料庫所消耗的效能更高,而記憶體比較很快.

結論:exists()適合B表比A表資料大的情況

當A表資料與B表資料一樣大時,in與exists效率差不多,可任選一個使用.

在查詢的兩個表大小相當的情況下,3種查詢方式的執行時間通常是:
EXISTS <= IN <= JOIN
NOT EXISTS <= NOT IN <= LEFT JOIN
只有當表中欄位允許NULL時,NOT IN的方式最慢:
NOT EXISTS <= LEFT JOIN <= NOT IN

但是如果兩個表中一個較小,一個較大,則子查詢表大的用exists,子查詢表小的用in,因為in 是把外表和內表作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。



下面再看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);

看查詢1,還是和上面一樣,用了B的索引

而對於查詢2,可以轉化成如下語句

select * from A where A.id != 1 and A.id != 2 and A.id != 3;

可以知道not in是個範圍查詢,這種!=的範圍查詢無法使用任何索引,等於說A表的每條記錄,都要在B表裡遍歷一次,檢視B表裡是否存在這條記錄

故not exists比not in效率高

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

如果查詢的兩個表大小相當,那麼用in和exists差別不大。  如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:  例如:表A(小表),表B(大表) 1: 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列的索引。  相反的 2: 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 extsts 的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。  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'  的結果是相同的。

相關推薦

mysqlinexists效率比較

這條語句適用於a表比b表大的情況 select * from ecs_goods a where cat_id in(select cat_id from ecs_category); 這條語句適用於b表比a表大的情況select * from ecs_goods

mysqlinexists的效能效率對比

有一種說法,說exists效能比in要好,其實不全然。哪個效能更好,需要看具體的需求場景。1、如何選擇使用in 或者 exists?1)子表資料量比外表資料量少,使用in。2)子表資料量比外表資料量大

MYSQLINEXISTS的區別

目錄 3、結論: 在MYSQL的連表查詢中,最好是遵循‘小表驅動大表的原則’ 一、IN與EXISTS的區別 1、IN查詢分析 SELECT   *  FROM A WHERE id IN (SELECT id FROM B); 等價於:1、SELECT

面試被問之-----sql優化inexists的區別 Mysql in or exists not exists not in區別 (網路整理) Sql語句INexists的區別及應用 [筆記] SQL效能優化 - 避免使用 IN 和 NOT IN

曾經一次去面試,被問及in與exists的區別,記得當時是這麼回答的:''in後面接子查詢或者(xx,xx,xx,,,),exists後面需要一個true或者false的結果",當然這麼說也不算錯,但別人想聽的是sql優化相關,肯定是效率的問題,只是那個時候確實不知道它們在sql優化上的區別,只知道用in會進

mysql inexists的區別

有兩張表:student 和 studentcource student 表 studentcource 表 需求:查詢所有成績小宇60分的同學 in 原理: 1、先查詢 <60 學生得到student_id列表 select student_id

Mysql in or exists not exists not in區別 (網路整理)

in 和or區別:https://www.cnblogs.com/rainwang/p/4389282.html 如果in和or所在列有索引或者主鍵的話,or和in沒啥差別,執行計劃和執行時間都幾乎一樣。 如果in和or所在列沒有 索引的話,效能差別就很大了。在沒有索引的情況下,隨著in或者or後面

ORACLE inexists語句的區別(一)

select * from A where id in(select id from B) 以上查詢使用了in語句,in()只執行一次,它查出B表中的所有id欄位並快取起來.之後,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有

Oracle inexists、not in,not exists比較

src inf .... blog pos str bug class exists 最基本的區別: in 對主表使用索引 exists 對子表使用索引 not in 不使用索引 not exists 對主子表都使用索引 寫法: exist的where條件是: "..

MySQL優化(5):索引失效分析、inexists使用場合

有一個 來替 null 決定 index idt class 分布 family 一、索引失效的情況   前文提及過可以通過explain的possible_keys、key屬性判斷索引是否失效,key如果為null,可能是索引沒建,也可能是索引失效,下面列舉一些會使索引失

mysql資料庫 INEXISTS 的誤區

       前言:最近在看 《高效能mysql第三版》 這本書,讀到子查詢優化那章,書中說mysql會將in子查詢改寫成exists查詢(書中基於的mysql版本是5.1.50和5.5),於是乎我又上網找了下資料,發現網上說法幾乎都是: &

mysqlnullnot null的區別及效率

<span style="font-family: 宋體; background-color: rgb(255, 255, 255);">經常用mysql的人可能會遇到下面幾種情況:</span> 1、我欄位型別是not null,為什麼我可以插入空值 2、為什麼not

oracleinexist的用法比較

最近在工作中用到oracle的in函式,但是該函式的引數個數存在上限(1000)的限制,而且涉及查詢的兩個表還在兩個不同的資料庫中,就無法使用exists函式來替代in的使用了。但還是總結一下in與exists的用法差異。 1.in適用於內表比外表資料量小的場景:select * from te

mysqlIN,OR,BETWEEN效能比較

這裡的查詢條件有三種:between,or 和 in。這裡id列是索引列,如果不是的話,三個查詢都是全表掃描,效能差距應該不大。   1  準備環境  程式碼如下 複製程式碼 mysql> show create table tinG **********

mysqllimitin不能同時使用的解決辦法

我就有以下的列子來解釋吧,這樣會更好的理解的! 一、新增teacher表和student表 teacher表 student表 二、假如只能同時二個人來查詢老師的資訊,請寫出sql語句實現 S

mysql inexists效能比較和使用

in 是把外表和內表作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的。 如果查詢的兩個表大小相當,那麼用in和exists差別不大。 如果兩個表中一個較小,一個是大表,則子查詢

SQL IN and Exists 效率高低比較

in 和exists in 是把外表和內表作hash 連線,而exists 是對外表作loop 迴圈,每次loop 迴圈再對內 表進行查詢。 一直以來認為exists 比in 效率高的說法是不準確的。 如果查詢的兩個表大小相當,那麼用in 和exists 差別不大。 如果兩個表中一個較小,一個是大表,則子查詢

SQL查詢inexists、not in、not exists的用法區別

1、in和exists in是把外表和內表作hash(字典集合)連線,而exists是對外表作迴圈,每次迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的,如果查詢的兩個表大小相當,那麼用in和exists差別不大;如果兩個表中一個較小一

Sql語句INexists的區別及應用

應用場景 將不 集中 pre 代碼 根據 gif 效率 .cn   表展示     首先,查詢中涉及到的兩個表,一個user和一個order表,具體表的內容如下:     user表:          order表:        in     確定給定的值是否與子查

in exists區別

相同 子查詢 exists zha tex 結果 sele ext zhang in和existsin 是把外表和內表作hash 連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢。如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子

ORACLE inexists語句的區別(一)

表數 內存 全部 sel 一個 性能 where 情況 lec (轉載:https://www.cnblogs.com/iceword/archive/2011/02/15/1955337.html) select * from Awhere id in(select id