mysql优化连接查询

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

我有一个数据库,里面有500k个公司简介+他们提供服务的地点。所以我有公司表+地点表。公司可以服务于全国,也可以只服务于一个城市。位置表如下所示:

  1. ID | company_id | scope | country_id | city_id
  2. 1 | 'companyuuid...' | 'city' | 'UK' | '32321'
  3. 2 | 'companyuuid...' | 'country' | 'US' | NULL

当公司在全国范围内提供服务时,我们标明范围“国家”,当公司只在特定城市内提供服务时,我们有范围“城市”。
不幸的是,mysql在处理有“or”语句的查询时非常慢,考虑到需要处理的数据量,查询应该尽可能优化。

  1. select distinct companies.id from companies
  2. inner join locations on companies.id = locations.company_id
  3. and (locations.scope = 'city' and locations.city_id = '703448' )
  4. order by companies.score desc limit 12 offset 0

我现在的问题是,在一个城市里寻找公司时,我还需要向全国范围内提供服务的公司展示。显而易见的方法是添加或声明如下:

  1. select distinct companies.id from companies
  2. inner join locations on companies.id = locations.company_id
  3. and (locations.scope = 'city' and locations.city_id = '703448' )
  4. or (locations.scope = 'country' and locations.country_id = 'UK' )
  5. order by companies.score desc limit 12 offset 0

但问题是or语句会使查询速度非常慢。有没有其他方法可以使用额外的连接,这样我们可以保持查询的速度?

fcg9iug3

fcg9iug31#

我建议使用 exists :

  1. select c.id
  2. from companies c
  3. where exists (select 1
  4. from locations l
  5. where l.company_id = c.id and
  6. l.scope = 'city' and
  7. l.city_id = 703448 -- I'm guessing city_id is a number, so no quotes
  8. ) or
  9. exists (select 1
  10. from locations l
  11. where l.company_id = c.id and l.scope = 'country'
  12. )
  13. order by c.score desc
  14. 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) .

相关问题