Commit 66e4e1db0e for woocommerce
commit 66e4e1db0e5222881db108d889ff77db84573abd
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date: Tue Jan 20 08:32:58 2026 +0100
[Performance] Admin: reduce the number of SQL queries needed for fetching settings (#62853)
In this PR, we leverage `wp_prime_option_caches` to bulk-prefetch entries from the options table used further in the settings context. When the cache is primed, `get_option` uses the in-memory cache rather than issuing SQL queries for each entry.
diff --git a/plugins/woocommerce/changelog/performance-admin-reduce-sqls-number-settings b/plugins/woocommerce/changelog/performance-admin-reduce-sqls-number-settings
new file mode 100644
index 0000000000..f082a0a1af
--- /dev/null
+++ b/plugins/woocommerce/changelog/performance-admin-reduce-sqls-number-settings
@@ -0,0 +1,4 @@
+Significance: patch
+Type: performance
+
+The number of SQL queries required to fetch settings on admin pages has been reduced to improve performance.
diff --git a/plugins/woocommerce/includes/class-wc-emails.php b/plugins/woocommerce/includes/class-wc-emails.php
index 4f137a43c3..959fd22936 100644
--- a/plugins/woocommerce/includes/class-wc-emails.php
+++ b/plugins/woocommerce/includes/class-wc-emails.php
@@ -272,29 +272,40 @@ class WC_Emails {
// Include email classes.
include_once __DIR__ . '/emails/class-wc-email.php';
- $this->emails['WC_Email_New_Order'] = include __DIR__ . '/emails/class-wc-email-new-order.php';
- $this->emails['WC_Email_Cancelled_Order'] = include __DIR__ . '/emails/class-wc-email-cancelled-order.php';
- $this->emails['WC_Email_Customer_Cancelled_Order'] = include __DIR__ . '/emails/class-wc-email-customer-cancelled-order.php';
- $this->emails['WC_Email_Failed_Order'] = include __DIR__ . '/emails/class-wc-email-failed-order.php';
- $this->emails['WC_Email_Customer_Failed_Order'] = include __DIR__ . '/emails/class-wc-email-customer-failed-order.php';
- $this->emails['WC_Email_Customer_On_Hold_Order'] = include __DIR__ . '/emails/class-wc-email-customer-on-hold-order.php';
- $this->emails['WC_Email_Customer_Processing_Order'] = include __DIR__ . '/emails/class-wc-email-customer-processing-order.php';
- $this->emails['WC_Email_Customer_Completed_Order'] = include __DIR__ . '/emails/class-wc-email-customer-completed-order.php';
- $this->emails['WC_Email_Customer_Refunded_Order'] = include __DIR__ . '/emails/class-wc-email-customer-refunded-order.php';
- $this->emails['WC_Email_Customer_Invoice'] = include __DIR__ . '/emails/class-wc-email-customer-invoice.php';
- $this->emails['WC_Email_Customer_Note'] = include __DIR__ . '/emails/class-wc-email-customer-note.php';
- $this->emails['WC_Email_Customer_Reset_Password'] = include __DIR__ . '/emails/class-wc-email-customer-reset-password.php';
- $this->emails['WC_Email_Customer_New_Account'] = include __DIR__ . '/emails/class-wc-email-customer-new-account.php';
-
+ $emails = array(
+ 'WC_Email_New_Order' => __DIR__ . '/emails/class-wc-email-new-order.php',
+ 'WC_Email_Cancelled_Order' => __DIR__ . '/emails/class-wc-email-cancelled-order.php',
+ 'WC_Email_Customer_Cancelled_Order' => __DIR__ . '/emails/class-wc-email-customer-cancelled-order.php',
+ 'WC_Email_Failed_Order' => __DIR__ . '/emails/class-wc-email-failed-order.php',
+ 'WC_Email_Customer_Failed_Order' => __DIR__ . '/emails/class-wc-email-customer-failed-order.php',
+ 'WC_Email_Customer_On_Hold_Order' => __DIR__ . '/emails/class-wc-email-customer-on-hold-order.php',
+ 'WC_Email_Customer_Processing_Order' => __DIR__ . '/emails/class-wc-email-customer-processing-order.php',
+ 'WC_Email_Customer_Completed_Order' => __DIR__ . '/emails/class-wc-email-customer-completed-order.php',
+ 'WC_Email_Customer_Refunded_Order' => __DIR__ . '/emails/class-wc-email-customer-refunded-order.php',
+ 'WC_Email_Customer_Invoice' => __DIR__ . '/emails/class-wc-email-customer-invoice.php',
+ 'WC_Email_Customer_Note' => __DIR__ . '/emails/class-wc-email-customer-note.php',
+ 'WC_Email_Customer_Reset_Password' => __DIR__ . '/emails/class-wc-email-customer-reset-password.php',
+ 'WC_Email_Customer_New_Account' => __DIR__ . '/emails/class-wc-email-customer-new-account.php',
+ );
if ( FeaturesUtil::feature_is_enabled( 'point_of_sale' ) ) {
- $this->emails['WC_Email_Customer_POS_Completed_Order'] = include __DIR__ . '/emails/class-wc-email-customer-pos-completed-order.php';
- $this->emails['WC_Email_Customer_POS_Refunded_Order'] = include __DIR__ . '/emails/class-wc-email-customer-pos-refunded-order.php';
+ $emails['WC_Email_Customer_POS_Completed_Order'] = __DIR__ . '/emails/class-wc-email-customer-pos-completed-order.php';
+ $emails['WC_Email_Customer_POS_Refunded_Order'] = __DIR__ . '/emails/class-wc-email-customer-pos-refunded-order.php';
}
-
if ( FeaturesUtil::feature_is_enabled( 'fulfillments' ) ) {
- $this->emails['WC_Email_Customer_Fulfillment_Created'] = include __DIR__ . '/emails/class-wc-email-customer-fulfillment-created.php';
- $this->emails['WC_Email_Customer_Fulfillment_Updated'] = include __DIR__ . '/emails/class-wc-email-customer-fulfillment-updated.php';
- $this->emails['WC_Email_Customer_Fulfillment_Deleted'] = include __DIR__ . '/emails/class-wc-email-customer-fulfillment-deleted.php';
+ $emails['WC_Email_Customer_Fulfillment_Created'] = __DIR__ . '/emails/class-wc-email-customer-fulfillment-created.php';
+ $emails['WC_Email_Customer_Fulfillment_Updated'] = __DIR__ . '/emails/class-wc-email-customer-fulfillment-updated.php';
+ $emails['WC_Email_Customer_Fulfillment_Deleted'] = __DIR__ . '/emails/class-wc-email-customer-fulfillment-deleted.php';
+ }
+
+ // Preload the options which will be used when emails are getting initialized in the loop below (reduces the number of SQL-queries).
+ wp_prime_option_caches(
+ array_map(
+ fn( string $class_name ) => sprintf( 'woocommerce_%s_settings', strtolower( str_replace( 'WC_Email_', '', $class_name ) ) ),
+ array_keys( $emails )
+ )
+ );
+ foreach ( $emails as $class => $path ) {
+ $this->emails[ $class ] = include $path;
}
/**
diff --git a/plugins/woocommerce/includes/rest-api/Controllers/Version1/class-wc-rest-customers-v1-controller.php b/plugins/woocommerce/includes/rest-api/Controllers/Version1/class-wc-rest-customers-v1-controller.php
index abad2afe45..5bc451ef2c 100644
--- a/plugins/woocommerce/includes/rest-api/Controllers/Version1/class-wc-rest-customers-v1-controller.php
+++ b/plugins/woocommerce/includes/rest-api/Controllers/Version1/class-wc-rest-customers-v1-controller.php
@@ -42,6 +42,14 @@ class WC_REST_Customers_V1_Controller extends WC_REST_Controller {
* Register the routes for customers.
*/
public function register_routes() {
+ // Preload the options which will be used in this method (reduces the number of SQL-queries).
+ wp_prime_option_caches(
+ array(
+ 'woocommerce_registration_generate_username',
+ 'woocommerce_registration_generate_password',
+ )
+ );
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
diff --git a/plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php b/plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php
index 0884dfe592..a3cdc6f421 100644
--- a/plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php
+++ b/plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-setting-options-v2-controller.php
@@ -172,6 +172,8 @@ class WC_REST_Setting_Options_V2_Controller extends WC_REST_Controller {
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
}
+ $this->prime_options_cache_for_settings( $settings );
+
$filtered_settings = array();
foreach ( $settings as $setting ) {
$option_key = $setting['option_key'];
@@ -206,6 +208,30 @@ class WC_REST_Setting_Options_V2_Controller extends WC_REST_Controller {
return $filtered_settings;
}
+ /**
+ * Primes options cache to reduce the number of SQLs towards options table.
+ *
+ * @param mixed[] $settings The settings to prefetch options for.
+ * @return void
+ */
+ protected function prime_options_cache_for_settings( array $settings ): void {
+ $prefetch = array();
+ foreach ( $settings as $setting ) {
+ $option_key = $setting['option_key'];
+ if ( is_array( $option_key ) ) {
+ $prefetch[] = $option_key[0];
+ } elseif ( strstr( $option_key, '[' ) ) {
+ parse_str( $option_key, $option_array );
+ $prefetch[] = current( array_keys( $option_array ) );
+ } else {
+ $prefetch[] = $option_key;
+ }
+ }
+ if ( array() !== $prefetch ) {
+ wp_prime_option_caches( $prefetch );
+ }
+ }
+
/**
* Returns a list of countries and states for use in the base location setting.
*
diff --git a/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-setting-options-controller.php b/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-setting-options-controller.php
index 8cd1e56ff5..5d9336a254 100644
--- a/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-setting-options-controller.php
+++ b/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-setting-options-controller.php
@@ -82,6 +82,8 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Setting_Options_V2_Cont
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
}
+ $this->prime_options_cache_for_settings( $settings );
+
$filtered_settings = array();
foreach ( $settings as $setting ) {
$option_key = $setting['option_key'];
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings.php b/plugins/woocommerce/src/Internal/Admin/Settings.php
index 51a7fc648f..26ffa1e42b 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings.php
@@ -154,6 +154,7 @@ class Settings {
//phpcs:ignore
$preload_options = apply_filters( 'woocommerce_admin_preload_options', array() );
if ( ! empty( $preload_options ) ) {
+ wp_prime_option_caches( $preload_options );
foreach ( $preload_options as $option ) {
$settings['preloadOptions'][ $option ] = get_option( $option );
}