Tom*_*Kay 9 mysql group-by sql-order-by left-join
我有一个查询的问题,这需要太长时间(这个简单的查询超过两秒).
首先看它似乎是一个索引问题,所有连接的字段都被编入索引,但我找不到我可能需要索引的其他内容以加快这一点.只要我添加查询所需的字段,它就会变得更慢.
SELECT `jobs`.`job_id` AS `job_id` FROM tabledef_Jobs AS jobs
LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
GROUP BY `jobs`.`job_id`
ORDER BY `jobs`.`date_posted` ASC
LIMIT 0 , 50
Run Code Online (Sandbox Code Playgroud)
表行数(〜):tabledef_Jobs(108k),tabledef_JobCatLink(109k),tabledef_Companies(100),tabledef_Applications(50k)
在这里你可以看到描述.'使用临时'似乎是减慢查询速度的原因:

表索引截图:




任何帮助将不胜感激
用答案编辑
感谢@Steve(标记答案)的最终改进查询.最终,最终查询从~22s减少到~0.3s:
SELECT `jobs`.`job_id` AS `job_id` FROM
(
SELECT * FROM tabledef_Jobs as jobs ORDER BY `jobs`.`date_posted` ASC LIMIT 0 , 50
) AS jobs
LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
GROUP BY `jobs`.`job_id`
ORDER BY `jobs`.`date_posted` ASC
LIMIT 0 , 50
Run Code Online (Sandbox Code Playgroud)
对,我会捅这个.
看起来查询优化器似乎无法使用索引来完成tabledef_Jobs表上的查询.
你有一个偏移限制,这与你的ORDER BY的组合不能限制加入前的数据量,因此它必须按job_id分组,这是一个PK和快 - 但然后订购该数据(临时表和一个filesort)在限制和丢弃这些数据的大部分之前,最后加入其他所有内容.
我建议,为"job_id,date_posted"的作业添加一个复合索引
首先优化基本查询:
SELECT * FROM tabledef_Jobs
GROUP BY job_id
ORDER BY date_posted
LIMIT 0,50
Run Code Online (Sandbox Code Playgroud)
然后,您可以将连接和最终结构组合在一起,以提高查询效率.
如果不建议你重新考虑你的限制抵消,我不能放过它.这适用于小的初始偏移,但是当它开始变大时,这可能是性能问题的主要原因.例如,让我们说你正在使用它进行分页,如果他们想要第3,000页会发生什么 - 你会使用
LIMIT 3000, 50
Run Code Online (Sandbox Code Playgroud)
然后,这将收集3050行/操纵数据,然后丢弃前3000.
[ 编辑1 - 回应以下评论]
我将扩展一些可能指向正确方向的信息.不幸的是,没有一个简单的解决方案可以解决它,你必须理解为什么会发生这种情况才能解决它.简单地删除LIMIT或ORDER BY可能不起作用,毕竟你不想删除它作为你的查询的一部分,这意味着它必须存在于某个目的.
首先优化简单的基本查询,这通常比使用多连接数据集容易得多.
尽管它收到了所有的抨击,但是filesort没有任何问题.有时这是执行查询的唯一方法.同意它可能是许多性能问题的原因(特别是在较大的数据集上),但这通常不是filesort的错误,而是底层的查询/索引策略.
在MySQL中,您不能混合索引或混合相同索引的订单 - 执行此类任务将导致文件排序.
我建议在date_posted上创建一个索引,然后使用:
SELECT jobs.job_id, jobs.date_posted, jobcats .*, apps.*, company .* FROM
(
SELECT DISTINCT job_id FROM tabledef_Jobs
ORDER BY date_posted
LIMIT 0,50
) AS jobs
LEFT JOIN tabledef_JobCatLink AS jobcats ON jobs.job_id = jobcats.job_id
LEFT JOIN tabledef_Applications AS apps ON jobs.job_id = apps.job_id
LEFT JOIN tabledef_Companies AS company ON jobs.company_id = company.company_id
Run Code Online (Sandbox Code Playgroud)