mysql优化连接查询

kzipqqlq  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(272)

我有一个数据库,里面有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语句会使查询速度非常慢。有没有其他方法可以使用额外的连接,这样我们可以保持查询的速度?

fcg9iug3

fcg9iug31#

我建议使用 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) .

vzgqcmou

vzgqcmou2#

问题1: OR 似乎“错了”。你要英国所有的城市,加上所有的伦敦,包括加拿大的那一个。
你可能想要 AND 而不是 OR . 你需要一个“自我连接”才能进入 locations 两次??eav架构很糟糕。
问题2: x AND y OR z(x AND y) OR z ,不是 x AND (y OR z) .

相关问题