【问题标题】:MySQL join performance with order by for large tables. Missing index?MySQL join 性能与大表的 order by。缺少索引?
【发布时间】:2020-10-03 07:15:18
【问题描述】:

我有以下两张表:

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 表:

【问题讨论】:

  • 请张贴SHOW CREATE TABLE <tablename> 的两个表的结果。这将使我们更好地了解指数。
  • 请在代码问题中提供minimal reproducible example--包括剪切、粘贴和可运行的最小代码以及以代码形式给出的最小代表性数据。对于包含 DBMS 和 DDL 的 SQL,包括约束、索引和表格初始化。对于包括 EXPLAIN 结果和统计信息的 SQL 性能。请研究和总结。对于包括优化/性能基础的 SQL——立即导致索引、计划、统计和 SARGability。 Tips for asking a good SQL question 学习并应用这些基础知识后,请重新优化。 How to Ask
  • 请use text, not images/links, for text--including tables & ERDs。仅将图像用于无法表达为文本或扩充文本的内容。
  • 并将那些SHOW CREATE TABLEs 提供为文本,而不是图像。

标签: mysql join indexing


【解决方案1】:

您有一个没有索引但在 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

【讨论】:

  • 已经有两个以file_id为第一列的复合索引:file_id, created_at & file_id, email_sha256。我不认为 file_id, id 会有所作为(如果我错了,请纠正我)
  • ... 在 where/ 子句中你有 file_id, id ..所以这是我的建议.. 无论如何.. 你可以试试。
猜你喜欢
  • 2011-05-17
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多