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

标签 mysql wordpress performance subquery taxonomy

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

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

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


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


当前查询:

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

最佳答案

参见 this great post关于 IN 的使用以及它如何对查询速度产生负面影响。这上面写满了您的问题。

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

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

If the inner and outer queries return M and N rows, respectively, the execution time becomes on the order of O(MxN), rather than O(M+N) as it would be for an uncorrelated subquery.

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

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

关于mysql - 如何优化这个非常慢的 MySQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23683086/

相关文章:

javascript - 如果 javascript 中的元素数量为奇数,我想定位网格的最后一项

mysql - Sequelize - 查询 Sequelize 方法

php - 为每个类别打印观看次数最多的视频

php - 如何检查MySQL中是否存在一行? (即检查 MySQL 中是否存在用户名或电子邮件)

php - Wordpress SQL查询不同的结果

php - WordPress MediaWiki 集成

language-agnostic - 维护或衡量集合排序的最佳方法是什么,以便我们可以选择最佳排序算法?

ruby-on-rails - 了解Ruby on Rails的渲染时间

Android 数据绑定(bind) DatabindingUtil 与绑定(bind)类

mysql - 如何在 WHERE IN 子句中使用字符串函数结果