我试图更好地理解为什么这个查询优化如此重要(超过100倍),所以我可以为其他查询重用类似的逻辑。
使用MySQL 4.1 - 在所有查询和结果时间可以一致地再现之前,重置QUERY CACHE和FLUSH TABLES。在EXPLAIN上,对我来说唯一明显的事情是在JOIN期间只需要找到5行?但这是速度的全部答案吗?两个查询都使用部分索引(forum_stickies)来确定已删除的主题状态(topic_status = 0)
使用EXPLAIN进行更深入分析的屏幕截图
慢查询:0.7秒(缓存清除)
SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics
WHERE topic_last_post_id IN
(SELECT SQL_NO_CACHE MAX (topic_last_post_id) AS topic_last_post_id
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id)
快速查询:0.004秒或更短时间(缓存清除)
SELECT SQL_NO_CACHE forum_id, topic_id FROM bb_topics AS s1
JOIN
(SELECT SQL_NO_CACHE MAX(topic_last_post_id) AS topic_last_post_id
FROM bb_topics WHERE topic_status=0 GROUP BY forum_id) AS s2
ON s1.topic_last_post_id=s2.topic_last_post_id
请注意,最重要的列(topic_last_post_id
)上没有索引,但无法提供帮助(无论如何都会存储结果以供重复使用)。
答案是否只是因为第一个查询必须扫描topic_last_post_id
TWICE,第二次将结果与子查询匹配?如果是这样,为什么它会指数速度变慢?
(不太重要我很好奇为什么第一个查询仍然花了这么长时间,如果我确实在topic_last_post_id
上放了一个索引)
更新:我在稍后进行了大量搜索之后在stackoverflow上发现了这个帖子,这个问题进入了这个主题Subqueries vs joins
答案 0 :(得分:4)
也许引擎为bb_topics中的每一行执行子查询,只是为了查看它是否在结果中找到了topic_last_post_id。会是愚蠢的,但也会解释巨大的差异。
答案 1 :(得分:0)
我想说,因为IN()子句中的参数可以是你坚持的任何内容,DB必须检查返回的所有内容。当你加入表格时,会采用许多性能增强策略,例如它可能会使用索引来实现它的优势。