我有两个表:
行程,列为user_id和bike_id
experiment_exposures ,带有subject_type和subject_id列
subject_type
可以是User
或Bike
,而subject_id
对应于user_id
或bike_id
。
前两个查询都相对较快,它们花费的时间大致相同:
select count(*)
from trips
join experiment_exposures e1 on e1.subject_type = 'User' and e1.subject_id = trips.user_id
join experiment_exposures e2 on e2.subject_type = 'Bike' and e2.subject_id = trips.bike_id;
和
select count(*)
from trips
join (select * from experiment_exposures where subject_type = 'User') e1 on e1.subject_id = trips.user_id
join (select * from experiment_exposures where subject_type = 'Bike') e2 on e2.subject_id = trips.bike_id;
但是,此查询的速度至少要慢100倍:
select count(*)
from trips
join experiment_exposures e
on (e.subject_type = 'User' and e.subject_id = trips.user_id)
or (e.subject_type = 'Bike' and e.subject_id = trips.bike_id);
为什么会有如此大的差异?第一个查询和第三个查询不是基本相同吗?凭直觉,我希望第三个查询会更快,因为只有1个联接。
答案 0 :(得分:2)
第三个查询是不同的!如果存在匹配项,它将返回其他行,而不是其他列。
在您的情况下,count()
甚至都不一样。
只是一个小例子:
user_id bike_id
1 1
1 2
ee_id subject_type subject_id
1 bike 1
2 bike 2
3 user 1
您的前两个联接产生一个中间表,如下所示:
user_id bike_id ee_id_user ee_id2_bike
1 1 3 1
1 2 3 2
第二个返回:
user_id bike_id ee_id subject_id
1 1 3 user
1 2 1 bike
1 1 3 user
1 2 2 bike
因此结果完全不同。
不过,您的问题是关于性能的。这是相关的,但非等分联接的效率通常比等联接低得多。当没有相应的等式时,这适用于OR
子句中的IN
和ON
(以及其他不等式)。