WooCommerce电商开发:高性能订单存储HPOS性能基准测试

自去年以来,我们一直致力于构建和推出 HPOS(高性能订单存储)作为一项可选功能。这改变了我们在数据库中存储订单数据的方式,从自定义帖子类型 wp_postwp_postmeta表到专门用于存储订单数据的自定义表。我们还发布了这些表的详细结构:高性能订单存储:数据库模式

您可以在WooCommerce 自定义订单表的计划中了解此更改的动机。

现在,我们很高兴通过分享我们一直在做的高性能订单存储HPOS性能基准测试的结果,与大家分享HPOS将带来的性能提升。我们将比较基于帖子的存储与 HPOS 在常见功能和查询(例如订单创建、过滤等)方面的性能。

目录  隐藏 

设置和方法

测试订单创建

基准代码

结果

订单结账

基准代码

结果

使用元数据搜索订单

基准代码

结果

按索引列过滤

基准代码

结果

使用非索引列搜索订单

基准代码

结果

数据库大小

结论

下一步

设置和方法

我们将在我们的测试站点上运行这些测试,该测试站点已经有大约 40 万个订单和 3 万个产品。该网站运行在一个商业计划中,每月收费 25 美元。该站点memcached启用并安装了缓存(主机标准产品的一部分),但该站点上没有其他特定的性能插件处于活动状态。

我们将在 WP shell 中运行查询,这意味着我们不会利用主机提供的并行性。换句话说,我们将只使用一个 worker,这相当于在一个请求中完成所有工作,而主机实际上并行提供了更多的 worker,即主机可以并行处理许多 Web 请求。这就是说,网站的整体性能比我们的基准测试在这里建议的要高得多。

我们还禁用了 HPOS <> 后同步,因为启用它会破坏基准测试的目的,尤其是对于订单创建流程。您可以在高性能订单存储:向后兼容性和同步中阅读有关同步如何工作的更多信息。我们预计最终商店将在其网站上永久禁用同步。

此外, WP 6.1 中引入的WP query cache 性能提升也被禁用,因此我们的查询实际上会访问数据库。

该站点上的表大小wp_postmeta约为 2GB(140 万行),表大小wp_posts约为 240MB(60 万行)。

请注意,使用的 WooCommerce 版本是开发版本,构建在cot-main分支上。这有稳定性修复,目前在主干中不可用,但应该很快可用(这些补丁正在审查周期中)。

测试

我们将使用一些直接查询进行测试,因为它们可以最直接地触发被测系统,而不会受到请求其他部分的干扰。

订单创建

通过减少我们为创建订单而必须执行的插入查询的数量,创建订单被确定为该项目的主要目标之一。在这里,我们看到 顺序插入性能提高了大约 5 倍,这主要是因为我们现在需要运行更少的插入查询,因为多个元字段在自定义表中被展平了。

基准代码

function benchmark_hpos_create_usage() {
        global $wpdb;
        $product_id = 502197;
        $count = 1000;
 
        $product = wc_get_product( $product_id );
        $label = \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ? 'HPOS' : 'Posts table';
        $time = microtime( true );
        for ( $i = 0; $i < $count; $i++ ) {
                $order = new WC_Order();
                $order->set_billing_first_name( 'John' );
                $order->set_billing_address_2( '123' );
                $order->add_product( $product );
                $order->save();
                assert( $order->get_id() > 0 );
        }
        $time_taken = microtime( true ) - $time;
        echo "[$label] " . 'Time to create ' . $count . ' orders: ' . $time_taken . 's';
}

结果

[HPOS] 创建1000个订单的时间:15.181570053101s[帖子表]创建1000个订单的时间:78.124469995499s

订单结账

与上述类似,我们也期望结账性能有所提高。请注意,插入性能不会直接转化为结帐性能,因为后者涉及各种数据验证和触发器(例如库存管理、各种 do_action 和 apply_filter 挂钩、用户验证等)。

即便如此,在使用 HPOS 时,我们看到结账 (对于一种产品的简单结账)提高了约 1.5 倍:

基准代码

function hpos_benchmark_process_checkout() {
    $label = \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ? 'HPOS' : 'Posts table';
    wc_load_cart();
    $product = wc_get_product( 502197 );
  
    add_filter( 'woocommerce_payment_successful_result', function ( $result, $order_id ) {
        assert( $order_id > 0 );
        throw new Exception( 'Order created: ' . $order_id );
    }, 10, 3 );
  
    $_POST['terms'] = 1;
    $_POST['terms-field'] = 1;
    $_POST['createaccount'] = 1;
    $_POST['payment_method'] = 'cod';
    $_POST['billing_first_name'] = 'John';
    $_POST['billing_last_name'] = 'Doe';
    $_POST['billing_company'] = 'Company';
    $_POST['billing_address_1'] = '123 Main St';
    $_POST['billing_address_2'] = '';
    $_POST['billing_city'] = 'San Francisco';
    $_POST['billing_state'] = 'CA';
    $_POST['billing_postcode'] = '94107';
    $_POST['billing_country'] = 'US';
    $_POST['billing_email'] = 'test_' . time() . '@example.com';
    $_POST['billing_phone'] = '555-555-5555';
    $_POST['ship_to_different_address'] = 0;
  
    add_action( 'woocommerce_after_checkout_validation', function ( $data, $errors ) {
        if ( $errors->get_error_messages() ) {
            print_r( implode( $errors->get_error_messages() ) );
            throw new Exception( 'Validation failed: ' . implode( ', ', $errors->get_error_messages() ) );
        }
    }, 10, 2 );
  
    $time_taken = 0;
    for ( $i = 0; $i < 10; $i++ ) {
        wc_empty_cart( true );
        $checkout_nonce = wp_create_nonce( 'woocommerce-process_checkout' );
        $_REQUEST['woocommerce-process-checkout-nonce'] = $checkout_nonce;
        wc_clear_notices();
        WC()->cart->add_to_cart( $product->get_id(), 1 );
        benchmark_checkout( $time_taken );
    }
    wc_maybe_define_constant( 'DOING_AJAX', false );
    echo "[$label] " . 'Time to process 10 checkouts: ' . $time_taken . 's';
  
}
  
function benchmark_checkout( &$time_taken ) {
    $time = microtime( true );
    try {
        WC()->checkout()->process_checkout();
    } catch ( Exception $e ) {
        echo $e->getMessage();
    }
    $time_taken = $time_taken + ( microtime( true ) - $time );
}

结果

[HPOS] 处理 10 次结帐的时间:0.99165391921997s[帖子表] 处理 10 次结帐的时间:1.5086543560028s

使用元数据搜索订单

在 HPOS 项目中,我们还可以自由地在order_meta表上实现索引,这是我们在 post 表上没有的。如您所料, 添加索引可加快元查询查找速度,在以下基准测试代码中约为 10 倍。另一方面,额外的索引会降低插入速度,但这应该被扁平化带来的插入性能提升所抵消,如之前的测试所述。

基准代码

function benchmark_hpos_metadata() {
    $label = \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ? 'HPOS' : 'Posts table';
  
    $time = microtime( true );
  
    $query = new WC_Order_Query(
        array(
            'limit'      => 1000,
            'return'     => 'ids',
            'orderby'    => 'id',
            'order'      => 'DESC',
            'billing_address_index' => 'John    123      ',
            'meta_query' => array(
                array(
                    'key'     => '_billing_address_index',
                    'value'   => 'John    123      ',
                    'compare' => '=',
                ),
            ),
        )
    );
  
    $orders     = $query->get_orders();
    $time_taken = microtime( true ) - $time;
    assert( count( $orders ) === 1000 );
    echo "[$label] " . 'Time to search ' . count( $orders ) . ' orders by metadata: ' . $time_taken . 's';
}

结果

[HPOS] 按元数据搜索 1000 个订单的时间:0.052868127822876s[帖子表]按元数据搜索1000个订单的时间:0.63891506195068s

按索引列过滤

现在我们已经将几个 post_meta 键扁平化到它们自己的列中,我们还在相关的地方利用各个 meta_keys 上的索引。其中一个字段 customer_id 有自己的索引列,而在 post 表中,它存储在 _customer_user 元键中。 在 HPOS 中,这个获取客户所有订单的查询现在快 40 倍, 因为它可以使用列的索引 customer_id 。

基准代码

function benchmark_hpos_filter_customer() {
    $label = \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ? 'HPOS' : 'Posts table';
    $time = microtime( true );
    $query = new WC_Order_Query(
        array(
            'limit' => 1000,
            'return' => 'ids',
            'customer_id' => 56902779,
        )
    );
    $orders = $query->get_orders();
  
    $time_taken = microtime( true ) - $time;
    echo "[$label] " . 'Time to filter ' . count( $orders ) . ' orders for customer: ' . $time_taken . 's' . PHP_EOL;
}

结果

[HPOS] 为客户筛选 1000 个订单的时间:0.015961170196533s[帖子表]为客户过滤1000个订单的时间:0.59882402420044s

使用非索引列搜索订单

与上面类似,一些扁平化的列没有被索引。但是,我们仍然期望性能有所提高,因为搜索区域仍然从wp_postmeta之前的整个表格减少到每个订单只有一个条目。在下面的查询中, 这 为我们的数据库带来了高达 3 倍的改进。

基准代码

function benchmark_hpos_search_non_index_usage() {
    $label = \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ? 'HPOS' : 'Posts table';
  
    $time = microtime( true );
    if ( 'HPOS' === $label ) {
        $query = new WC_Order_Query(
            array(
                'limit'       => 1000,
                'return'      => 'ids',
                'orderby'     => 'id',
                'order'       => 'DESC',
                'field_query' => array(
                    array(
                        'field' => 'created_via',
                        'value' => 'checkout',
                    )
                )
            )
        );
    } else {
        $query = new WC_Order_Query(
            array(
                'limit'       => 1000,
                'return'      => 'ids',
                'orderby'     => 'id',
                'order'       => 'DESC',
                'created_via' => 'checkout'
  
            )
        );
    }
    $orders = $query->get_orders();
    assert( count( $orders ) === 1000 );
    $time_taken = microtime( true ) - $time;
    echo "[$label] " . 'Time to search orders: ' . $time_taken . 's' . PHP_EOL;
}

结果

[HPOS] 查询订单时间:0.29565596580505s[帖子表]搜索订单的时间:1.0048348903656s

数据库大小

借助 HPOS,我们通过移出与订单相关的所有条目在技术上对post-meta表进行分片。我们希望站点管理员最终能够删除属于订单的现有post-meta行,从而提高订单工作流之外的站点性能(因为较小的表大小意味着 MySQL 在查询期间扫描的行数较少)。

例如,在大型部署的 woocommerce.com 中,订单约占所有帖子记录的 81%。在 wp_postmeta 表中,这种偏差更大,属于订单的元记录约占所有行的 97%。如果我们要删除属于订单的帖子元记录(我们计划在 HPOS 运行一段时间后执行此操作),  woocommerce.com 将看到 post-meta表数据减少 97%。我们希望这种尺寸减小能够提高网站的整体性能,而不仅限于订单。

结论

如您所见,HPOS 提高了各种与订单相关的流程的性能,并有可能大大提高一般站点的性能。我们鼓励所有插件开发人员升级他们的插件以支持 HPOS,以便生态系统中的商家可以利用这个项目。

下一步

与查询基准类似,我们也在运行网络请求性能测试,并计划很快发布结果。

点击阅读 WooCommerce电商开发:高性能订单存储HPOS性能基准测试 原文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值