简体   繁体   English

优化 Wordpress 中的重度慢查询

[英]Optimize heavy slow query in Wordpress

I have a fairly large database - 162150 total of rows in wp_3_posts table and 521345 total of rows in wp_3_postmeta.我有一个相当大的数据库——wp_3_posts 表中共有 162150 行,wp_3_postmeta 中共有 521345 行。 I noticed that my site is very slow.我注意到我的网站速度很慢。 I noticed that the slow queries took like 10 seconds to load the page.我注意到缓慢的查询需要 10 秒来加载页面。


SELECT wp_3_posts.*
FROM wp_3_posts
INNER JOIN wp_3_postmeta
ON ( wp_3_posts.ID = wp_3_postmeta.post_id )
WHERE 1=1
AND ( ( wp_3_postmeta.meta_key = 'course_id'
AND wp_3_postmeta.meta_value = '157898' ) )
AND wp_3_posts.post_type IN ('sfwd-lessons', 'sfwd-topic', 'sfwd-quiz')
AND ((wp_3_posts.post_status = 'publish'
OR wp_3_posts.post_status = 'future'
OR wp_3_posts.post_status = 'draft'
OR wp_3_posts.post_status = 'pending'
OR wp_3_posts.post_status = 'private'))
GROUP BY wp_3_posts.ID
ORDER BY wp_3_posts.post_date DESC 

I found out that meta_query arguments causes the page slow.我发现 meta_query arguments 导致页面变慢。

$attr_defaults = array(
       'include_outer_wrapper' => 'true',
       'num'                   => false,
       'paged'                 => 1,
       'post_type'             => learndash_get_post_type_slug( 'course' ),
       'post_status'           => 'publish',
       'order'                 => 'DESC',
       'orderby'               => 'ID',
       'cat'                   => '',
       'category_name'         => 0,
       'category__and'         => '',
       'category__in'          => '',
       'category__not_in'      => '',
       'categoryselector'      => '',
       'show_thumbnail'        => 'true',
       'show_content'          => 'true',
       'col'                   => '',
       'progress_bar'          => 'false',
       'array'                 => false,
       'course_grid'           => 'true',
       
       'update_post_term_cache' => false, // don't retrieve post terms
       'update_post_meta_cache' => false, // don't retrieve post meta
       'no_found_rows' => true, // counts posts, remove if pagination required 
   );

This is the table I am trying to optimize the meta_query arguments:这是我试图优化 meta_query arguments 的表:

$enrollquery = $wpdb->get_results( $wpdb->prepare("SELECT Users.ID, Users.user_login, Users.display_name, Learndash.activity_type, PostObject.post_status, PostObject.post_title, PostObject.post_type FROM `wp_users` AS `Users`INNER JOIN `wp_3_learndash_user_activity` AS `Learndash` ON Users.ID = Learndash.user_id INNER JOIN `wp_3_posts` AS `PostObject` ON PostObject.ID = Learndash.post_id INNER JOIN `wp_3_postmeta` AS `Postmeta` ON PostObject.ID = Postmeta.post_id WHERE Users.ID = '".$current_user->ID."' GROUP BY PostObject.ID"));

Is there a way to optimize that?有没有办法优化它?

First第一的

Your question's second query is this, formatted.您的问题的第二个查询是格式化的。

SELECT Users.ID, Users.user_login, Users.display_name, 
       Learndash.activity_type, 
       PostObject.post_status, PostObject.post_title, PostObject.post_type
  FROM wp_users AS Users
 INNER JOIN wp_3_learndash_user_activity AS Learndash ON Users.ID = Learndash.user_id
 INNER JOIN wp_3_posts AS PostObject ON PostObject.ID = Learndash.post_id
 INNER JOIN wp_3_postmeta AS Postmeta ON PostObject.ID = Postmeta.post_id
 WHERE Users.ID = '".$current_user->ID."'
 GROUP BY PostObject.ID

I think it has a mistake in it.我认为它有一个错误。 You do an INNER JOIN from posts to postmeta , but you don't include a meta_key filter.您执行从postspostmeta的 INNER JOIN,但不包含meta_key过滤器。 That means the query picks up all the postmeta rows for the post in question.这意味着查询会获取相关帖子的所有postmeta行。 That probably isn't right.那可能是不对的。 It definitely makes the query handle a lot of extra data, only to have it removed by your GROUP BY.它肯定会使查询处理大量额外数据,只是为了让您的 GROUP BY 将其删除。

Usually postmeta joins look something like this:通常postmeta连接看起来像这样:

 INNER JOIN wp_3_postmeta AS Postmeta
        ON PostObject.ID = Postmeta.post_id
       AND Postmeta.meta_key = 'course_id'  /* or some other constant */ 

Pro tip always format your queries in your source code so you can read them easily.专业提示始终在您的源代码中格式化您的查询,以便您可以轻松阅读它们。 php allows multiline string constants. php 允许多行字符串常量。

Second第二

According to LearnDash's help page its table is defined根据LearnDash 的帮助页面,其表已定义

CREATE TABLE wp_learndash_user_activity (
  activity_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  user_id bigint(20) unsigned NOT NULL DEFAULT '0',
  post_id bigint(20) unsigned NOT NULL DEFAULT '0',
  activity_type varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  activity_status tinyint(1) unsigned DEFAULT '0',
  activity_started int(11) unsigned DEFAULT NULL,
  activity_completed int(11) unsigned DEFAULT NULL,
  activity_updated int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (activity_id),
  KEY user_id (user_id),
  KEY post_id (post_id),
  KEY activity_status (activity_status),
  KEY activity_type (activity_type),
  KEY activity_started (activity_started),
  KEY activity_completed (activity_completed),
  KEY activity_updated (activity_updated)
)

That table could use a change to an index, extending the user_id index to cover your query.该表可以使用对索引的更改,扩展user_id索引以覆盖您的查询。 You can do this with any MySQL client program.您可以使用任何 MySQL 客户端程序执行此操作。 Make a backup first, and do it in a quiet time on your site .首先进行备份,并在您站点上的安静时间进行备份 But, unless your users each do large numbers of activities, this index probably won't help much.但是,除非您的每个用户都进行大量活动,否则该索引可能不会有太大帮助。

ALTER TABLE wp_3_learndash_user_activity
    DROP INDEX user_id,
    ADD INDEX user_id (user_id, post_id, activity_type);

Third第三

Your indexes on posts and postmeta need changing too.您在postspostmeta上的索引也需要更改。 There's a plugin to handle those changes.有一个插件可以处理这些更改。 Index WP MySQL For Speed .索引 WP MySQL 对于速度 It creates indexes to cover queries like yours, described here .它创建索引来覆盖像您这样的查询, 如这里所述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM