我有一个数据库,其中包含50万个公司简介及其提供服务的位置。 所以我有公司表+位置表。 公司可以在全国范围内或仅在一个城市中提供服务。 位置表如下所示:
ID | company_id | scope | country_id | city_id
1 | 'companyuuid...' | 'city' | 'UK' | '32321'
2 | 'companyuuid...' | 'country' | 'US' | NULL
当公司在全国范围内提供服务时,我们将范围“国家”标明,而当公司仅在特定城市内提供服务时,我们将范围“城市”标明。
不幸的是,当MySQL具有“ OR”语句并考虑到需要处理的数据量时,MySQL处理查询的速度会非常慢。
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
我当前的问题是,在城市中寻找公司时,我还需要展示在全国范围内提供服务的公司。显而易见的方法是添加如下的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' )
or (locations.scope = 'country' and locations.country_id = 'UK' )
order by companies.score desc limit 12 offset 0
但是问题是OR语句会使查询非常慢。 也许还有其他使用附加联接的方法,这样我们可以使查询保持快速吗?
答案 0 :(得分:0)
我建议使用exists
:
select c.id
from companies c
where exists (select 1
from locations l
where l.company_id = c.id and
l.scope = 'city' and
l.city_id = 703448 -- I'm guessing city_id is a number, so no quotes
) or
exists (select 1
from locations l
where l.company_id = c.id and l.scope = 'country'
)
order by c.score desc
limit 12 offset 0;
exists
子查询可以利用locations(company_id, scope, city_id)
上的索引。该查询甚至可以利用companies(score)
上的索引。
答案 1 :(得分:0)
问题1:OR
似乎是“错误的”。您要英国的所有城市,再加上伦敦的所有城市,包括加拿大的所有城市吗?
您可能希望使用AND
而不是OR
。您将需要“自我加入”才能两次进入locations
? EAV模式糟透了。
问题2:x AND y OR z
是(x AND y) OR z
,而不是x AND (y OR z)
。