我有一个数据库,里面有500k个公司简介+他们提供服务的地点。所以我有公司表+地点表。公司可以服务于全国,也可以只服务于一个城市。位置表如下所示:
ID | company_id | scope | country_id | city_id
1 | 'companyuuid...' | 'city' | 'UK' | '32321'
2 | 'companyuuid...' | 'country' | 'US' | NULL
当公司在全国范围内提供服务时,我们标明范围“国家”,当公司只在特定城市内提供服务时,我们有范围“城市”。
不幸的是,mysql在处理有“or”语句的查询时非常慢,考虑到需要处理的数据量,查询应该尽可能优化。
select distinct companies.id from companies
inner join locations on companies.id = locations.company_id
and (locations.scope = 'city' and locations.city_id = '703448' )
order by companies.score desc limit 12 offset 0
我现在的问题是,在一个城市里寻找公司时,我还需要向全国范围内提供服务的公司展示。显而易见的方法是添加或声明如下:
select distinct companies.id from companies
inner join locations on companies.id = locations.company_id
and (locations.scope = 'city' and locations.city_id = '703448' )
or (locations.scope = 'country' and locations.country_id = 'UK' )
order by companies.score desc limit 12 offset 0
但问题是or语句会使查询速度非常慢。有没有其他方法可以使用额外的连接,这样我们可以保持查询的速度?
2条答案
按热度按时间fcg9iug31#
我建议使用
exists
:这个
exists
子查询可以使用上的索引locations(company_id, scope, city_id)
. 查询甚至可以利用上的索引companies(score)
.vzgqcmou2#
问题1:
OR
似乎“错了”。你要英国所有的城市,加上所有的伦敦,包括加拿大的那一个。你可能想要
AND
而不是OR
. 你需要一个“自我连接”才能进入locations
两次??eav架构很糟糕。问题2:
x AND y OR z
是(x AND y) OR z
,不是x AND (y OR z)
.