2014-05-15 47 views
2

我有一个基于WordPress的网站,它为一本地区科学杂志编目的学术文章。如何优化这个非常慢的MySQL查询?

简而言之,系统有几千个“职位”,并且每个系统都有一个“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小时运行一次。

我知道这里的主要问题是我已经对所有东西都使用了子查询。虽然我想了解更多关于使用连接的知识,但我还不知道以其他方式编写此查询。

任何人都可以提供一些见解或建议,我怎么能驯服这个野兽?

编辑:下面是查询结果输出的解释截图:

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

+1

很多子查询时间,'WHERE EXISTS'比'WHERE IN'快。但是,为了给您一个更好的答案,我需要查看查询计划。你可以在你的问题中加入'EXPLAIN PLAN'输出吗? –

+1

如果我想去那里,我不会从这里出发。 :-(考虑提供适当的DDLs(和/或一个sqlfiddle)与期望的结果集 – Strawberry

+0

你是说你想要这么做:计算pub_type分类的每个词的帖子数量? – pmandell

回答

0

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

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

在这里面,从MySQL手册笔者引号:

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

使用该逻辑,则必须在wp_posts作为外部查询,并在其内,在10行嵌套wp_terms_relationship,和内嵌套,wp_terms一次。那一个是949*(10*1))。第二次你只有两层嵌套,但是因为最后一层只有一行,所以它仍然有相同的影响:你最终将解析9490行。

子查询不是你的朋友。虽然有时他们可能是必要的,但他们几乎总是可以使用JOIN解决。根据你的目标,这看起来不太一样。通过重写这个查询并试图使用JOIN...ON,你会发现经过一段简短的学习曲线后,它将会更容易地读取你自己的代码,遵循其逻辑进程,并且很有可能看到它也加速了。至少,在可以的地方使用join。你稍后会感谢你。