Mysql相关子查询与连接性能

Mysql相关子查询与连接性能,mysql,Mysql,我一直认为连接比子查询快。然而,对于小数据集中的一个非常简单的查询,联接在1.0s内返回,而相关子查询在0.001s内返回。好像有什么不对劲。我注意到这两个查询都使用了正确的(名称惊人的)索引。对于联接而言,超过1秒似乎过多。有什么想法吗 请将这两个查询与其解释计划进行比较: a) 使用连接 select user.id, user.username, count(distinct bet_placed.id) as bets_placed, count(distinct bet_won.id

我一直认为连接比子查询快。然而,对于小数据集中的一个非常简单的查询,联接在1.0s内返回,而相关子查询在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"
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"
平均响应时间:1.0秒

b) 使用相关子查询

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   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"
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秒

请参见


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

“较小”的数据集(但可能与数据库的设置方式以及所使用的DBMS不同)可能没有什么区别(无论哪种方式),但正如您所看到的

但是,相对于其他“查询类型”,这些操作比其他操作快得多(如下所示):


子查询与联接

在非常复杂的情况下,子查询和联接解决方案的性能都相当好 涉及小分区(每个分区最多几百行) 分区)。随着分区大小的增长,这些 溶液以二次(N2)方式降解,变得非常差。 但只要分区很小,性能就会下降 分区数量的增加是线性的。一个因素 这可能会影响您在使用基于子查询或 join-based solution是请求的聚合数。正如我 如前所述,基于子查询的方法需要单独扫描 每个聚合的数据,而基于连接的方法则不然 在需要时,您很可能希望使用join方法 计算多个聚合


~

很有趣,但是我想知道这里是否有区别,因为所有这些信息都是基于SQLServer的,而我使用的是MySQL。非常不同的引擎。