如何优化这个非常慢的MySQL查询?

时间:2014-05-15 15:49:31

标签: mysql wordpress performance subquery taxonomy

我有一个基于WordPress的网站,为区域科学期刊编写学术文章目录。

简单地说,系统有几千个“帖子”,每个都有一个“pub_type”分类标准,其中只选择了1个术语:“手稿”,或者别的。

每个帖子还有与之相关的各种其他分类/术语。


目标:获取特定分类标准的术语列表。对于每个术语,计算与其相关的帖子数量,并确定有多少帖子在“pub_type”分类中设置了“手稿”。


当前查询:

SELECT term_id, term_id as term_id_b, name, slug,
( SELECT COUNT(id) FROM wp_posts WHERE id IN 
    ( SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN 
        ( SELECT term_taxonomy_id FROM wp_term_taxonomy WHERE term_id = term_id_b ) 
) AND post_status = "publish" ) as count,
( SELECT COUNT(id) FROM wp_posts WHERE id IN 
    ( SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN 
        ( SELECT term_taxonomy_id FROM wp_term_taxonomy WHERE term_id IN 
            ( SELECT term_id FROM wp_terms WHERE term_id = term_id_b ) 
        )
    ) 
AND id IN 
( SELECT object_id FROM wp_term_relationships WHERE term_taxonomy_id IN
    ( SELECT term_taxonomy_id FROM wp_term_taxonomy WHERE term_id = 
        ( SELECT term_id FROM wp_terms WHERE name = "Manuscript" ) 
    AND taxonomy = "pub_type" )
)
AND post_status = "publish"
) as manuscript_count
FROM wp_terms 
WHERE term_id IN 
( SELECT term_id FROM wp_term_taxonomy WHERE taxonomy = "'.$taxonomy.'" )
ORDER BY name ASC

虽然此查询可以正常运行,但运行速度非常慢......在3-5分钟之间,具体取决于服务器负载。这是非常糟糕的,为了保持网站性能,我不得不将查询结果缓存到JSON文本文件中,并且只让查询每2小时运行一次。

我知道这里的主要问题是我使用了子查询。虽然我正在尝试了解有关使用联接的更多信息,但我还不知道以其他方式编写此查询。

任何人都可以提供一些有关如何驯服这种野兽的见解或建议吗?

编辑:以下是查询的EXPLAIN输出的屏幕截图:

http://i.imgur.com/Axaqun3.png

1 个答案:

答案 0 :(得分:0)

有关IN的使用以及它如何对查询速度产生负面影响,请参阅this great post。这就是你的问题。

基本上,使用传统的IN(values)查询,您只需搜索每个值。在子查询IN中(IN(SELECT))。

其中,作者引用了MySQL的手册:

  

如果内部和外部查询分别返回M行和N行,则执行时间变为O(MxN)的顺序,而不是O(M + N),就像对于不相关的子查询一样。

使用此逻辑,您将wp_posts作为外部查询,并在其中嵌套wp_terms_relationship 10行,并且 嵌套,wp_terms再次。那个是949*(10*1))。第二次你只有两个级别的嵌套,但由于最终级别只有一行,它仍然是同样的影响:你最终解析了9490行。

子查询不是你的朋友。虽然有时它们可​​能是必要的,但它们几乎总是可以使用JOIN来解决。根据您的目标,这似乎并没有太大的不同。通过重写此查询并进行拉伸以尝试使用JOIN...ON,您会发现在经过简短的学习曲线之后, 更容易阅读您自己的代码,遵循其逻辑进展,并且,最有可能的是,看到它也加快了。至少,尽可能利用join。你以后会感谢自己。