2012-06-20 183 views
0

我的目標是選擇其中primary_category_idarticles表)或任何 次級類別(articles_secondary_categories連接表)爲給定值的文章。在這個示例查詢中,類別1.我嘗試使用其他類型的連接,但是這裏需要注意的是文章可能沒有任何第二類別。優化MySQL LEFT JOIN查詢

SELECT DISTINCT articles.* 
FROM articles 
LEFT JOIN articles_secondary_categories AS categories 
    ON categories.article_id = articles.id 
WHERE 
(
    primary_category_id = 1 
    OR 
    categories.category_id = 1 
) 
    AND articles.state = "published" 
    AND edition_id = 1 

ORDER BY publish_at DESC 
LIMIT 10; 

歡迎任何有關優化或替代的幫助。在具有4k articles和7k articles_secondary_categories(不是類別)的數據庫中,運行此查詢需要5秒鐘的時間。

+0

什麼執行時間結果沒有WHERE(...)子句? – odiszapc

+0

你的問題是你如何優化這個查詢運行在少於5秒? – daniellopez46

+0

DISTINCT真的需要在這裏嗎? – raina77ow

回答

0

則可以反向查詢次級類:

(SELECT articles.* 
FROM articles 
WHERE primary_category_id = 1) 
UNION DISTINCT 
(SELECT articles.* 
FROM articles_secondary_categories AS categories 
JOIN articles ON (categories.article_id = articles.id) 
WHERE categories.category_id = 1 
GROUP BY articles_id) 
ORDER BY publish_at DESC 
LIMIT 10; 

它應該給你一個體面的速度提升 - 只要確保你指數的WHERE子句中使用categories.articles_id OR

+0

這是最快的,但我們最終結束了重組我們的表格,以更好地適應我們正在做的查詢。 – bloudermilk

0

避免。優化器通常不會使用與謂詞相關的索引。

嘗試移動categories.category_id = 1到加盟條件:

SELECT articles.* 
FROM articles 
LEFT JOIN articles_secondary_categories AS categories 
    ON categories.article_id = articles.id and categories.category_id = 1 
WHERE 1 in (ifnull(categories.category_id, primary_category_id), primary_category_id) 
AND articles.state = "published" 
AND edition_id = 1 
ORDER BY publish_at DESC 
LIMIT 10; 

的關鍵,這個查詢1 in (ifnull(categories.category_id, primary_category_id), primary_category_id),它說:「如果我們得到了加盟的類別,使用列表,否則使用primary_category_id,並在所有情況下使用primary_category_id