我一直认为联接比子查询更快。但是,对于小数据集中的非常简单的查询,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秒
答案 0 :(得分:1)
请参阅
显示了不同类型查询的速度/行比较。
可能在'较小'数据集上存在很少/没有差异(无论哪种方式)(但可能已经设置了数据库以及使用的DBMS),但正如您所看到的,< / p>
但是,与其他“查询类型”相比,它们比其他操作(如下所示)快得多:
子查询与加入
子查询和联接解决方案在非常好的情况下表现得相当好 涉及小分区(每个最多几百行) 划分)。随着分区大小的增长,这些的性能 解决方案以二次(N2)方式降级,变得非常差。 但只要分区很小,性能就会下降 由分区数量增加引起的是线性的。一个因素 这可能会影响您在使用基于子查询或 基于连接的解决方案是请求的聚合数。就像我一样 讨论过,基于子查询的方法需要单独扫描 每个聚合的数据,而基于联接的方法不是这样 您很可能希望在需要时使用加入方法 计算多个聚合。