这个 WordPress MySQL 数据库查询有什么问题?

What's wrong with this WordPress MySQL DB Query?

我有一个非常繁忙的 wordpress 网站。每月超过 300 万次网页浏览。过去几周我们遇到了 MySQL 个问题。 CPU 超过 500%(8 核,256GB RAM,专用硬件)和非常慢的性能。

所以我找到了这个查询几十次。

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 = 'tie_views')
 AND wp_posts.post_type = 'post'
 AND ((wp_posts.post_status = 'publish'))
 GROUP BY wp_posts.ID
 ORDER BY wp_postmeta.meta_value+0
 DESC LIMIT 0, 20

看来是在等待超时,然后被杀死。有人可以解释一下这到底是什么吗?谁能告诉我这个查询有什么问题?

请指教...

此查询本身没有任何问题。我修改了它以使用我拥有的数据库,并且我能够在 0.0409 秒内获取 10,000 记录(在具有 21k posts 记录和 137k postmeta 记录的数据库上).也就是说,我还稍微修改了我的数据库,包括 postmeta table 上的部分索引,这确实加快了这些查询的速度。

您会在 WordPress 中注意到的一件事是,越来越大的网站变得越来越慢,尤其是在使用 meta_query 时。 (通常,当您在同一个 table 和 OR […] WHERE 上使用多个 JOIN 时,情况会更糟且更明显。

有一百万个 Articles/SO Questions/Docs 关于“在 WordPress 中加速慢速元查询”,不幸的是,您将自己找到适合您的方法。

如果该查询被 运行 数十次(每次页面加载??)确保您正在缓存结果。确保你有一些好的 Object Caching,并考虑页面缓存 - 如果你还没有的话。

您还可以考虑使用 WordPress Transients 缓存该查询的结果 - 这基本上将查询结果设置为 wp_options table 中的临时选项一段时间您确定(30 秒、4 小时、6 周,等等)- 它将从那里拉出而不是每次 运行 查询,直到它过期。

最后一件可能相关也可能不相关的事情是,确保您的 wp_options table 没有肿胀。许多插件会在其中留下大量臃肿的信息。默认存储选项将它们设置为 autoload: true,这意味着它们会在 每次加载页面 时加载到内存中。我见过“lightweight/small/etc”网站,这些网站有一个臃肿的 wp_options table,里面有数百兆字节的旧垃圾,导致极端的加载时间、超时和崩溃。

所以基本上

  • 寻找加速元查询的方法,因为它们本来就很慢
  • 打开对象缓存and/or使用 WP Transients
  • 考虑页面缓存
  • 清除选项中无用的垃圾table

WP 的基本设计是“EAV”(Entity-Attribute-Value)。这是存储活动数据点(例如 view-counter 或“Like”计数器)的一种非常低效的方法。而且,正如您所发现的,它无法很好地扩展。

此类计数器应位于数据类型为 numericdedicated 列中。我不知道 WP 中是否有办法添加这样的列。假设这是不可能的,以下将通过改进 postmeta 的索引来帮助 somehttp://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta