首页 > 解决方案 > MySQL join 性能与大表的 order by。缺少索引?

问题描述

我有以下两个表:

requests: id, file_id

request_filter_integers: id, request_filter_id, value

我想使用以下查询获取数据:

select `requests`.`id`, `sum_followers`.`value` as `sum_followers`
from `requests`
  left join `request_filter_integers` as `sum_followers` on `sum_followers`.`request_id` = `requests`.`id` and `sum_followers`.`request_filter_id` in (63002331)
where `requests`.`file_id` in (3571851, 3574928, 3576373, 10000857, 10001207, 10001258, 10001516, 10001528)
order by `sum_followers`.`value` desc limit 51 offset 0

这个查询需要很长时间,我不确定是否存在索引/顺序问题,或者它是否通常受到表结构/连接设置方式的限制。requests 包含大约 1.5 亿行,具有 10k 个不同的 file_id。request_filter_integers 有 1.3 亿行。查询中的 where file_id IN 子句将请求行限制为 100 万。

解释上述查询返回:

在此处输入图像描述 我有以下索引:

请求表: 在此处输入图像描述

request_filter_integers 表:

在此处输入图像描述

标签: mysqljoinindexing

解决方案


您有一个没有索引但在 where 子句中使用的请求 file_id 列

所以你应该对列上的表请求使用复合索引(file_id, id )

并且您还应该避免为几个值使用 IN 子句,您可以尝试使用连接。(使用联合子查询或 IN 值的适当表)

子查询为

select 3571851 file_id 
union 
select 3574928 
union 
select 3576373 
union 
select 10000857 
union 
select 10001207 
union 
select 10001258 
union 
select 10001516 
union 
select 10001528 

应该返回相同的值,并且可以通过这种方式修改您的查询

select `requests`.`id`, `sum_followers`.`value` as `sum_followers`
from `requests`
INNER JOIN ( 
    select 3571851 file_id 
    union 
    select 3574928 
    union 
    select 3576373 
    union 
    select 10000857 
    union 
    select 10001207 
    union 
    select 10001258 
    union 
    select 10001516 
    union 
    select 10001528
    ) t o t.file_id = requests.file_id
left join `request_filter_integers` as `sum_followers` on `sum_followers`.`request_id` = `requests`.`id` 
and `sum_followers`.`request_filter_id` in (63002331)
order by `sum_followers`.`value` desc limit 51 offset 0

推荐阅读