优化MySQL LEFT JOIN查询

时间:2012-06-20 00:36:13

标签: mysql sql join left-join

我的目标是选择primary_category_idarticles表)或其中任何一个的文章 辅助类别(articles_secondary_categories连接表)是给定值。在此示例查询中,类别1.我尝试使用其他类型的连接,但这里需要注意的是文章可能没有任何辅助类别。

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秒钟。

2 个答案:

答案 0 :(得分: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;

它应该给你一个不错的速度提升 - 只需确保你索引categories.articles_id

答案 1 :(得分:0)

避免在where子句中使用OR。优化器通常不使用带有OR谓词的索引。

尝试将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。