我的查询问题花了太长时间(这个简单的查询仅用了两秒钟)。
首先看起来它似乎是一个索引问题,所有连接的字段都被编入索引,但我找不到我可能需要索引的其他内容以加快速度。一旦我添加了查询所需的字段,它就会变得更慢。
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
表行数(〜):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
答案 0 :(得分:6)
是的,我会抓住这个。
看起来查询优化器无法使用索引来完成tabledef_Jobs表的查询。
你有一个偏移限制,这与你的ORDER BY的组合不能限制加入前的数据量,因此它必须按job_id分组,这是一个PK并且速度快 - 但是然后订购该数据(临时的) table和filesort)在限制和丢弃这些数据的大部分之前,最后加入其他所有内容。
我建议,为“job_id,date_posted”
的作业添加复合索引首先优化基本查询:
SELECT * FROM tabledef_Jobs
GROUP BY job_id
ORDER BY date_posted
LIMIT 0,50
然后,您可以将连接和最终结构组合在一起,以提高查询效率。
如果不建议你重新考虑你的限制抵消,我不能放过它。这适用于小的初始偏移,但是当它开始变大时,这可能是性能问题的主要原因。让我们举例说明你是用它来分页,如果他们想要第3,000页会发生什么 - 你会用
LIMIT 3000, 50
这将收集3050行/操纵数据,然后扔掉前3000个。
[编辑1 - 回应以下评论]
我将扩展一些可能指向正确方向的信息。不幸的是,没有一个简单的解决方案可以解决它,你必须理解为什么会发生这种情况才能解决它。简单地删除LIMIT或ORDER BY可能不起作用,毕竟你不想删除它作为你的查询的一部分,这意味着它必须在那里。
首先优化简单基本查询,这通常比使用多连接数据集容易得多。
尽管遭受了所有抨击但却没有任何文件错误。有时这是执行查询的唯一方法。同意它可能是许多性能问题的原因(特别是在较大的数据集上),但这通常不是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