[wp-trac] [WordPress Trac] #61025: Do not write in DB when updating a user if no user data has changed
WordPress Trac
noreply at wordpress.org
Wed Apr 17 15:32:34 UTC 2024
#61025: Do not write in DB when updating a user if no user data has changed
-------------------------+-----------------------------
Reporter: asumaran | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Users | Version: 6.5
Severity: normal | Keywords:
Focuses: performance |
-------------------------+-----------------------------
I've been working on improving the response times when checking out using
WooCommerce.
We use Hyper DB with a separate host for writes. Subsequent reads are
affected after every write. Avoiding any write query helps.
I noticed there's a duplicate query when checking out.
{{{
#!sql
UPDATE `wp_users` SET `user_pass` = '$P$BlixIWEMbCbx76WhYlGoBnta7X8Bgf.',
`user_nicename` = 'foo1713310736', `user_email` =
'foo1713310736 at mail.test', `user_url` = '', `user_registered` =
'2024-04-16 23:38:56', `user_activation_key` = '', `display_name` =
'foo1713310736' WHERE `ID` = 180
}}}
Turns out, WC creates a new cutomer using `wc_create_new_customer`
[https://github.com/woocommerce/woocommerce/blob/ec80c8d641c9636f610cbcc4124c7600712bcf50/plugins/woocommerce/includes
/data-stores/class-wc-customer-data-store.php#L112C9-L112C31 which] under
the good
[https://github.com/woocommerce/woocommerce/blob/ec80c8d641c9636f610cbcc4124c7600712bcf50/plugins/woocommerce/includes
/wc-user-functions.php#L109 uses] `wp_insert_user` and then lines
[https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes
/class-wc-checkout.php#L1154 below]
[https://github.com/woocommerce/woocommerce/blob/ec80c8d641c9636f610cbcc4124c7600712bcf50/plugins/woocommerce/includes
/class-wc-checkout.php#L1187 updates] the customer using
`WC_Customer->save()` method which under the hood uses `wp_update_user`
which also uses `wp_insert_user`.
At first I've tried to fix it in WooCommerce's scope but the issue is in
the `wp_insert_user` function.
Since there's no hook to control the write, I'm proposing the same as
`update_metadata` is
[https://github.com/WordPress/WordPress/blob/6fe9681e77813d4543918eeafc735fb0c4fba250
/wp-includes/meta.php#L244-L246 already doing], if the passed value is the
same as the previous one then skip the write query.
Here's how to reproduce the improvement:
Run the following using WP Shell
{{{
#!php
$username = 'foo' . time();
$user_email = $username . '@mail.test';
$user_id = wp_insert_user([ 'user_login' => $username, 'user_pass' =>
'password', 'user_email' => $user_email ]);
wp_update_user( [ 'ID' => $user_id, 'user_email' => $user_email ] );
wp_update_user( [ 'ID' => $user_id, 'user_email' => $user_email ] );
wp_update_user( [ 'ID' => $user_id, 'user_email' => $user_email ] );
exit;
}}}
Small plugin to inspect queries
{{{
#!php
<?php
/*
* Plugin Name: Show Queries (@asumaran)
*/
if ( ! defined( 'SAVEQUERIES' ) ) {
define( 'SAVEQUERIES', true );
}
add_action( 'shutdown', 'output_queries' );
function output_queries() {
global $wpdb;
$queries = [];
foreach ( $wpdb->queries as $query ) {
if ( str_contains( $query[0], 'UPDATE `wp_users`' ) ) {
$queries[] = $query[0];
}
}
error_log( "\r\n" . print_r( join( "\r\n", $queries ), true ) );
}
}}}
Without the patch:
It should show 3 `UPDATE` to the `wp_users` table in the log
{{{
#!sql
UPDATE `wp_users` SET `user_pass` = '$P$BlDtStXHL/XErbE2J8VeILcjNOcVub.',
`user_nicename` = 'foo1713365151', `user_email` =
'foo1713365151 at mail.test', `user_url` = '', `user_registered` =
'2024-04-17 14:45:51', `user_activation_key` = '', `display_name` =
'foo1713365151' WHERE `ID` = 183
UPDATE `wp_users` SET `user_pass` = '$P$BlDtStXHL/XErbE2J8VeILcjNOcVub.',
`user_nicename` = 'foo1713365151', `user_email` =
'foo1713365151 at mail.test', `user_url` = '', `user_registered` =
'2024-04-17 14:45:51', `user_activation_key` = '', `display_name` =
'foo1713365151' WHERE `ID` = 183
UPDATE `wp_users` SET `user_pass` = '$P$BlDtStXHL/XErbE2J8VeILcjNOcVub.',
`user_nicename` = 'foo1713365151', `user_email` =
'foo1713365151 at mail.test', `user_url` = '', `user_registered` =
'2024-04-17 14:45:51', `user_activation_key` = '', `display_name` =
'foo1713365151' WHERE `ID` = 183
}}}
With the patch:
It shouldn't log any update queries to the `wp_users` table.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/61025>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list