与 wp_postmeta 连接的 wp_posts 内部的 Wordpress 慢查询

Posted

技术标签:

【中文标题】与 wp_postmeta 连接的 wp_posts 内部的 Wordpress 慢查询【英文标题】:Wordpress slow query on wp_posts inner joined with wp_postmeta 【发布时间】:2019-12-06 13:40:07 【问题描述】:

我的主页中有这个查询,非常慢,需要 4 秒才能执行。我的 wp_posts 表有 125672 行,我的 wp_postmeta 有 1405416 行。 此外,将 wp_posts 与 wp_postmeta 内部连接的所有其他查询都非常慢。

SELECT wp_posts.ID
FROM wp_posts 
INNER JOIN wp_postmeta
ON ( wp_posts.ID = wp_postmeta.post_id )
WHERE 1=1 
AND ( ( wp_postmeta.meta_key = 'home'
AND wp_postmeta.meta_value = '1' ) )
AND wp_posts.post_type IN ('post', 'training', 'video', 'startup')
AND ((wp_posts.post_status = 'publish'))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 1

【问题讨论】:

wp_postmeta.post_id 上应该有一个索引 - 你能检查一下它还在那里吗?您是否尝试过通常的 mysql 慢查询调试,例如EXPLAIN 查询? wp_posts 部分应该完全来自 type_status_date 索引,因此如果不是,则会出现问题。我知道这无关紧要,但你也可以尝试删除1=1,以防万一这令人不安? 如果您想要 DISTINCT 结果,请使用 DISTINCT,而不是 GROUP BY。是的,GROUP BY 更快,但这不是它的用途,在更复杂的情况下,你就像 a) 犯了一个错误,b) 没有意识到它。 【参考方案1】:

您可以尝试使用exists 重写此代码:

SELECT wp_posts.ID
FROM wp_posts p
WHERE EXISTS (SELECT 1
              FROM wp_postmeta pm
              WHERE p.ID = pm.post_id AND
                    pm.meta_key = 'home' AND
                    pm.meta_value = '1'
             ) AND
      p.post_type IN ('post', 'training', 'video', 'startup') AND
      p.post_status = 'publish'
ORDER BY p.post_date DESC
LIMIT 0, 1;

这摆脱了外部GROUP BY(或SELECT DISTINCT)。

然后,您需要索引。我会推荐:

wp_posts(post_status, post_type, id, post_date) wp_postmeta(post_id, meta_key, meta_value)

编辑:

另一种优化方法是从wp_postmeta开始:

SELECT p.id
FROM (SELECT pm.*
      FROM wp_postmeta pm
      WHERE p.ID = pm.post_id AND
            pm.meta_key = 'home' AND
            pm.meta_value = '1'
     ) pm JOIN
     wp_posts p
     ON p.ID = pm.post_id
WHERE p.post_type IN ('post', 'training', 'video', 'startup') AND
      p.post_status = 'publish'
ORDER BY p.post_date DESC
LIMIT 1;

为此,您需要wp_postmeta(meta_key, meta_value, post_id)posts(id) 上的索引(如果id 是主键,则后者默认存在)。

如果子查询中的过滤条件具有高度选择性,这将很有效。

【讨论】:

实际上,您的替代查询运行时与我现有的查询存在切片差异,差异为 0.13 秒,这不是很大。也添加索引并没有提高运行时间。 如果meta_valueLONGTEXT,则不能被索引。【参考方案2】:

你需要这个吗?

按 wp_posts.ID 分组

INDEX(post_status, post_type) 可能会有所帮助

请参阅我对post_meta 索引的建议:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta

【讨论】:

以上是关于与 wp_postmeta 连接的 wp_posts 内部的 Wordpress 慢查询的主要内容,如果未能解决你的问题,请参考以下文章

WHERE 子句中的一些错误

wordpress数据库表结构

WordPress数据结构分析

将 WP 帖子导入 WAMP localhost

WordPress数据库及各表结构分析

wordpress数据库结构以及数据表之间的关系