我的目标是选择primary_category_id
(articles
表)或其中任何一个的文章
辅助类别(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秒钟。
答案 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。