如何在超过200,000个订单的网站上加快“我的帐户>订单页面”的速度?

时间:2019-09-24 作者:dc09

在“我的帐户”>“订单”页面上,最慢的查询如下:

SELECT SQL_CALC_FOUND_ROWS 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 = \'_customer_user\'
AND wp_postmeta.meta_value IN (\'1\') ) ) )
AND wp_posts.post_type IN (\'shop_order\', \'shop_order_refund\')
AND ((wp_posts.post_status = \'wc-pending\'
OR wp_posts.post_status = \'wc-processing\'
OR wp_posts.post_status = \'wc-on-hold\'
OR wp_posts.post_status = \'wc-completed\'
OR wp_posts.post_status = \'wc-cancelled\'
OR wp_posts.post_status = \'wc-refunded\'
OR wp_posts.post_status = \'wc-failed\'
OR wp_posts.post_status = \'wc-cancel-request\'
OR wp_posts.post_status = \'wc-printing\'))
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10
加载页面需要7-10秒。这很可能是因为数据库中有200000多个订单。我尝试将post\\U状态限制为3种状态,而不是搜索所有状态的订单,但这没有帮助。如何加速“我的帐户”>“订单”页面?

1 个回复
SO网友:Daniel Espinoza

这是WooCommerce插件的一个问题。从3.7.0版本开始,我的帐户>;订单页面使用效率低下的查询来获取客户的订单。商店中有200000个订单,在wp\\U Posteta表中可能有50倍多的行。我刚刚在一个有60万帖子和3500万Posteta行的网站上遇到了同样的问题。

查询源运行“我的帐户”快捷码do_action(\'my_account_shortcode\')然后开火woocommerce_account_content().然后它就会开火do_action(woocommerce_account_orders_endpoint)哪个呼叫woocommerce_accont_orders().

这个wc_get_orders() 第3050行的调用是调用原始问题的查询。

潜在解决方案

1. Change the query to get customer\'s orders

要更改此查询,我添加了woocommerce_account_orders() 函数的主题,该主题将比WooCommerce更精确,并调用一个更简单的查询:

global $wpdb;
$user_id = get_current_user_id();
$sql     = "SELECT wp_postmeta.post_id FROM wp_postmeta WHERE wp_postmeta.meta_key = \'_customer_user\' AND wp_postmeta.meta_value = " . $user_id . " ORDER BY wp_postmeta.post_id DESC";
$results = $wpdb->get_results( $sql );
$orders  = wp_list_pluck( $results, \'post_id\' );

// Setup an array to send to the template.
$customer_orders[\'orders\'] = $orders;
$customer_orders[\'max_num_pages\'] = 1;

wc_get_template(
    \'myaccount/orders.php\',
        array(
        \'current_page\'    => absint( $current_page ),
        \'customer_orders\' => $customer_orders,
        \'has_orders\'      => 0 < count( $customer_orders[\'orders\'] ),
    )
);
对上述代码的可能改进:

我知道使用$wpdb 是不受欢迎的,但这是一个快速修复方法,可以显示该页面中减少的数据库负载

2. Override the orders template

您还需要覆盖\'myaccount/orders.php\' 主题和处理中的模板$customer_orders 作为数组而不是对象。

在里面this file 改变

foreach ( $customer_orders->orders as $customer_order ) {

到这个

foreach ( $customer_orders[\'orders\'] as $customer_order ) {

最后,原始查询提取“shop\\u order”和“shop\\u order\\u return”类型的帖子。您的商店可能有其他订单类型,如订阅。

在模板循环中,可以在wc_get_order() 例如:

// skip if this is a subscription 
if ( wcs_is_subscription( $order ) ){
   continue;
}