MySQL:Grouped / Ordered / Left Join查询非常慢

时间:2013-03-07 13:46:46

标签: 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

表行数(〜):tabledef_Jobs(108k),tabledef_JobCatLink(109k),tabledef_Companies(100),tabledef_Applications(50k)

在这里你可以看到描述。 “使用临时”似乎是减慢查询速度的原因:

enter image description here

表索引截图:

enter image description here

enter image description here

enter image description here

enter image description here

非常感谢任何帮助

以答案编辑

感谢@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

1 个答案:

答案 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