Mysql Correlated Subquery vs Join性能

时间:2014-12-17 10:43:32

标签: mysql

我一直认为联接比子查询更快。但是,对于小数据集中的非常简单的查询,Join返回1.0s,而Correlated-Subquery返回0.001s。似乎有些事情是错的。我注意到两个查询都使用了正确的(令人震惊的命名)索引。加入时超过1秒似乎过多。有什么想法吗?

请将这两个查询与他们的解释计划进行比较:

a)使用加入

select user.id, user.username, 
count(distinct bet_placed.id) as bets_placed,
count(distinct bet_won.id) as bets_won,
count(distinct bets_involved.id) as bets_involved
from user 
left join bet as bet_placed on bet_placed.user_placed = user.id 
left join bet as bet_won on bet_won.user_won = user.id 
left join bet_accepters as bets_involved on bets_involved.user = user.id 
group by user.id

解释计划:

id  select_type table   type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  user    index   PRIMARY PRIMARY 4   NULL    86  100.00  NULL
1   SIMPLE  bet_placed  ref fk_bet_user1_idx    fk_bet_user1_idx    4   xxx.user.id 6   100.00  "Using index"
1   SIMPLE  bet_won ref user_won_idx    user_won_idx    5   xxx.user.id 8   100.00  "Using index"
1   SIMPLE  bets_involved   ref FK_user_idx FK_user_idx 4   xxx.user.id 8   100.00  "Using index"

平均响应时间:1.0秒

b)使用Correlated-Subquery

select user.id, user.username, 
(select COALESCE(count(bet.id), 0) from bet where bet.user_placed = user.id) as bets_placed,
(select COALESCE(count(bet.id), 0) from bet where bet.user_won = user.id) as bets_won,
(select COALESCE(count(bet_accepters.id), 0) from bet_accepters where bet_accepters.user = user.id) as bets_involved
from user;

解释计划:

id  select_type table   type    possible_keys   key key_len ref rows    filtered    Extra
1   PRIMARY user    ALL NULL    NULL    NULL    NULL    86  100.00  NULL
4   "DEPENDENT SUBQUERY"    bet_accepters   ref FK_user_idx FK_user_idx 4   xxx.user.id 8   100.00  "Using index"
3   "DEPENDENT SUBQUERY"    bet ref user_won_idx    user_won_idx    5   xxx.user.id 8   100.00  "Using index"
2   "DEPENDENT SUBQUERY"    bet ref fk_bet_user1_idx    fk_bet_user1_idx    4   xxx.user.id 6   100.00  "Using index"

平均响应时间:0.001秒

1 个答案:

答案 0 :(得分:1)

请参阅


enter image description here

显示了不同类型查询的速度/行比较。

可能在'较小'数据集上存在很少/没有差异(无论哪种方式)(但可能已经设置了数据库以及使用的DBMS),但正如您所看到的,< / p>

但是,与其他“查询类型”相比,它们比其他操作(如下所示)快得多:

enter image description here


  

子查询与加入

     

子查询和联接解决方案在非常好的情况下表现得相当好   涉及小分区(每个最多几百行)   划分)。随着分区大小的增长,这些的性能   解决方案以二次(N2)方式降级,变得非常差。   但只要分区很小,性能就会下降   由分区数量增加引起的是线性的。一个因素   这可能会影响您在使用基于子查询或   基于连接的解决方案是请求的聚合数。就像我一样   讨论过,基于子查询的方法需要单独扫描   每个聚合的数据,而基于联接的方法不是这样   您很可能希望在需要时使用加入方法   计算多个聚合。

SOURCE