我正在使用MySQL 5.5。我有这3个表:新闻,NewsSubTopic,SubTopic。我想知道为什么这个查询很慢:
SELECT
DISTINCT COUNT(news0_.id) as col_0_0_
FROM
news news0_
INNER JOIN
news_sub_topic subtopics1_
ON
news0_.id = subtopics1_.news_sub_topics_id
INNER JOIN
sub_topic subtopic2_
ON
subtopics1_.sub_topic_id = subtopic2_.id
WHERE
(subtopic2_.id IN (55 , 134 , 135 , 52 , 53 , 32 , 54))
AND news0_.type = 'api';
我已经在news.type中放置了索引键。是否可以在NewsSubTopic中添加密钥?
以下是一些统计信息:新闻表有 1,088,126 条目,NewsSubTopic有 823,247 条目,SubTopic有 168 。
请注意,该查询是由Grails(或Hibernate)生成的。你能解释一下如何调试查询并理解它为什么慢(3-5秒)?还有其他方法可以改进它(我可以提供您需要的其他信息)。
答案 0 :(得分:4)
您不需要DISTINCT
,COUNT
的参数或对sub_topic
的引用:
SELECT COUNT(*)
FROM news_sub_topic ns
JOIN news n
ON n.id = ns.news_sub_topics_id
WHERE ns.sub_topic_id IN (55 , 134 , 135 , 52 , 53 , 32 , 54)
AND n.type = 'api'
在news_sub_topic (sub_topic_id, news_sub_topics_id)
请注意,DISTINCT COUNT(…)
和COUNT(DISTINCT …)
是不同的事情。如果您需要后者,请使用:
SELECT COUNT(DISTINCT n.id)
FROM news_sub_topic ns
JOIN news n
ON n.id = ns.news_sub_topics_id
WHERE ns.sub_topic_id IN (55 , 134 , 135 , 52 , 53 , 32 , 54)
AND n.type = 'api'
您能解释一下您想对查询做什么吗?
答案 1 :(得分:1)
尽管已经说过,但您的查询可能不是Sargable。 您需要为连接条件创建索引,以使您查询尽可能不敏感的news_sub_topics_id。
确保也使用非常有选择性的索引(按选择性排序索引字段(VerySelective,LessSelective,...)。
答案 2 :(得分:0)
我不明白你为什么要这样做:
...
ON
news0_.id = subtopics1_.news_sub_topics_id
不是NEWS.id不是它的PK而且在加入主题时你不想再使用像NEWS.topicid这样的专栏吗?
您可以先尝试剔除子主题:
select distinct newssubtopicid from newssubtopic as NS
inner join subtopic ST on NS.subtopicid = ST.id
and ST.id in (55 , 134 , 135 , 52 , 53 , 32 , 54)
ST.id是它的PK,不是吗? NS.subtopicid应该有一个索引。上面的查询需要多长时间?
此时,您知道提取相关新闻所需的新闻子主题:
select count(NEWS.id) from NEWS
inner join
(
select distinct newssubtopicid from newssubtopic as NS
inner join subtopic ST on NS.subtopicid = ST.id
and ST.id in (55 , 134 , 135 , 52 , 53 , 32 , 54)
) as T
on NEWS.topicid = T.newssubtopicid