我认为与您建议的子查询相比,第二个联接更好地利用这里的索引(只需要添加一个distinct以避免重复)。
SELECT SQL_NO_CACHE DISTINCT
resource.*, user.nickname
FROM resource
LEFT JOIN user ON user.id = resource.user_id
LEFT JOIN user_group ON user_group.user_id = user.id AND user_group.type IN (1, 2, 3)
WHERE user_id = '000000-0000-0000-0000-000000000000'
OR access_type = 3
OR (access_type = 2 AND group_id IS NOT NULL)
ORDER BY created DESC;
每当主WHERE子句是或的序列时,理想的解释结果将是某种索引合并。但是,你是对的,那种联合是最慢的。如果你继续读下去
index_merge
尤其是关于每种类型合并的子部分,很明显,where子句的or部分需要引用键的所有部分,否则将得到排序联合。因此,如果有资源索引,您应该得到更好的解释结果:
Resource (10K-100K)
id
user_id
access_type (int)
group_id
created (int/timestamp)
â¦
indexes
just_user(user_id),
by_user(user_id, created),
just_access(access_type),
just_access_group(access_type, group_id),
by_group(access_type, group_id, created),
public(access_type, created)
我认识到这似乎与当你做多部分键时,你可以免费得到左前缀作为索引相矛盾,但是看起来索引合并算法不能(还没有?)使用那些部分前缀索引。