码迷,mamicode.com
首页 > 其他好文 > 详细

小表驱动大表, 兼论exists和in

时间:2015-08-25 20:57:46      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

给出两个表,A和B,A和B表的数据量,

当A小于B时,用exists
select * from A where exists (select * from B where A.id=B.id)
exists的实现,相当于外表循环,每次循环对内表进行查询?
for i in A
    for j in B
        if j.id == i.id then ....
相反,如果A大于B的时候,则用in
select * from A where id in (select id from B)
这种在逻辑上类似于
for i in B
    for j in A
        if j.id == i.id then ....

 

然后MySQL实现in,使用了hash join (哈希连接)。我猜想和逻辑上的两层循环在工作原理上是不一样的。
 
经过我的实际测试
SELECT * FROM user u where exists  (SELECT 0 FROM plan p where p.user_id=u.user_id )
0.188 sec / 6.234 sec
 
SELECT * FROM user u where  user_id in  (SELECT user_id FROM plan)
0.015 sec / 0.000 sec
使用in的可谓是瞬间的
 
其中Plan表有3300行记录,User表有3800,数据量恰好接近。
所以那个伪码(两层循环只能帮助理解),和实际情况差距很大。否则二者应该非常接近才对。
 
  Duration Fetch Rows  SQL
exists 0.17 6.2 924 SELECT * FROM user u where exists  (SELECT 0 FROM plan p where p.user_id=u.user_id )
in 0.01 0.0 924 SELECT * FROM user u where  user_id in  (SELECT user_id FROM plan)
 虽然数据量很小,但是可以想象,如果我们用exists,可能会非常糟糕,难怪都建议用in。
 
(未完)
Hash Join
 
Not in
 

小表驱动大表, 兼论exists和in

标签:

原文地址:http://www.cnblogs.com/healerkx/p/4758295.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!