我有一个基于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输出的屏幕截图:
答案 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
。你以后会感谢自己。