2013-03-07 137 views
8

我有一個查詢需要很長時間(超過兩秒只是這個簡單的查詢)的問題。MySQL:分組/有序/左連接查詢非常慢

首先看起來它似乎是一個索引問題,所有連接的字段都被索引,但我找不到我可能需要索引的東西來加速它。只要我將查詢所需的字段添加,它就會變得更慢。

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 
+0

感謝固定圖像@XLAnt - 我沒有足夠的代表爲尚未:) – 2013-03-07 13:51:02

+0

嘗試添加一個索引到'date_posted'並讓我知道如果它改善 – jcho360 2013-03-07 14:00:04

+0

@ jcho360謝謝,但我以前曾嘗試在'date_posted'上添加索引,但不幸的是這沒有什麼區別。此外,我需要這個足夠靈活,以便可能接受'ORDER BY'子句中的不同字段。 – 2013-03-07 14:06:09

回答

6

對,我會刺傷這個。

看來查詢優化器不能使用索引來滿足tabledef_Jobs表上的查詢。

你有一個偏移限制,這與你的ORDER BY的組合不能限制加入之前的數據量,因此它不得不通過job_id這是一個PK和快速分組 - 但是然後命令該數據(臨時表和文件),然後再限制和拋棄這些數據中的大部分內容,然後再將其他所有內容加入其中。

我建議,增加了綜合指數的工作「JOB_ID,date_posted」

所以,首先優化了基本查詢:

SELECT * FROM tabledef_Jobs 
GROUP BY job_id 
ORDER BY date_posted 
LIMIT 0,50 

然後你可以結合連接和最終結構一起進行更有效的查詢。

我不能讓它通過而不建議你重新考慮你的極限偏移量。對於小的初始偏移量來說這很好,但當它開始變大時,這可能是性能問題的主要原因。讓我們舉例來說緣故說你想利用這個做分頁,如果他們想3000頁會發生什麼 - 你會使用

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 
+0

Hi @Steve,謝謝你的回答。如果我刪除'limit',查詢仍然需要相同的時間。然而出於興趣,我在'job_id'和'date_posted'上應用了一個複合索引。不幸的是這沒有什麼區別。 'explain'保持不變,'Using temporary'。謝謝 – 2013-03-07 14:39:34

+1

關於「限制」,這不是用於分頁的標準做法嗎?謝謝 – 2013-03-07 14:42:34

+1

@oridan偏移限制是快速簡單的分頁方式,但不是真正的方法。如果你谷歌,你會發現許多文章詳細解釋其他方法。 – Steve 2013-03-07 14:58:01