Commit 5b19de4034f for woocommerce

commit 5b19de4034f7252184e743714cd3a5f85f19f314
Author: Néstor Soriano <konamiman@konamiman.com>
Date:   Tue May 19 17:25:31 2026 +0200

    Restore the meta_value column in the meta_key_value index of the HPOS meta table (#65146)

diff --git a/plugins/woocommerce/changelog/fix-meta-key-value-index-removal b/plugins/woocommerce/changelog/fix-meta-key-value-index-removal
new file mode 100644
index 00000000000..86619e72bde
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-meta-key-value-index-removal
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Restore the meta_value column to the meta_key_value index on the wc_orders_meta table to fix a performance regression.
diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php
index a81552692bc..799d1d29bb3 100644
--- a/plugins/woocommerce/includes/class-wc-install.php
+++ b/plugins/woocommerce/includes/class-wc-install.php
@@ -46,7 +46,7 @@ class WC_Install {
 	 * @var array
 	 */
 	private static $db_updates = array(
-		'2.0.0'  => array(
+		'2.0.0'    => array(
 			'wc_update_200_file_paths',
 			'wc_update_200_permalinks',
 			'wc_update_200_subcat_display',
@@ -55,42 +55,42 @@ class WC_Install {
 			'wc_update_200_images',
 			'wc_update_200_db_version',
 		),
-		'2.0.9'  => array(
+		'2.0.9'    => array(
 			'wc_update_209_brazillian_state',
 			'wc_update_209_db_version',
 		),
-		'2.1.0'  => array(
+		'2.1.0'    => array(
 			'wc_update_210_remove_pages',
 			'wc_update_210_file_paths',
 			'wc_update_210_db_version',
 		),
-		'2.2.0'  => array(
+		'2.2.0'    => array(
 			'wc_update_220_shipping',
 			'wc_update_220_order_status',
 			'wc_update_220_variations',
 			'wc_update_220_attributes',
 			'wc_update_220_db_version',
 		),
-		'2.3.0'  => array(
+		'2.3.0'    => array(
 			'wc_update_230_options',
 			'wc_update_230_db_version',
 		),
-		'2.4.0'  => array(
+		'2.4.0'    => array(
 			'wc_update_240_options',
 			'wc_update_240_shipping_methods',
 			'wc_update_240_api_keys',
 			'wc_update_240_refunds',
 			'wc_update_240_db_version',
 		),
-		'2.4.1'  => array(
+		'2.4.1'    => array(
 			'wc_update_241_variations',
 			'wc_update_241_db_version',
 		),
-		'2.5.0'  => array(
+		'2.5.0'    => array(
 			'wc_update_250_currency',
 			'wc_update_250_db_version',
 		),
-		'2.6.0'  => array(
+		'2.6.0'    => array(
 			'wc_update_260_options',
 			'wc_update_260_termmeta',
 			'wc_update_260_zones',
@@ -98,26 +98,26 @@ class WC_Install {
 			'wc_update_260_refunds',
 			'wc_update_260_db_version',
 		),
-		'3.0.0'  => array(
+		'3.0.0'    => array(
 			'wc_update_300_grouped_products',
 			'wc_update_300_settings',
 			'wc_update_300_product_visibility',
 			'wc_update_300_db_version',
 		),
-		'3.1.0'  => array(
+		'3.1.0'    => array(
 			'wc_update_310_downloadable_products',
 			'wc_update_310_old_comments',
 			'wc_update_310_db_version',
 		),
-		'3.1.2'  => array(
+		'3.1.2'    => array(
 			'wc_update_312_shop_manager_capabilities',
 			'wc_update_312_db_version',
 		),
-		'3.2.0'  => array(
+		'3.2.0'    => array(
 			'wc_update_320_mexican_states',
 			'wc_update_320_db_version',
 		),
-		'3.3.0'  => array(
+		'3.3.0'    => array(
 			'wc_update_330_image_options',
 			'wc_update_330_webhooks',
 			'wc_update_330_product_stock_status',
@@ -126,48 +126,48 @@ class WC_Install {
 			'wc_update_330_set_paypal_sandbox_credentials',
 			'wc_update_330_db_version',
 		),
-		'3.4.0'  => array(
+		'3.4.0'    => array(
 			'wc_update_340_states',
 			'wc_update_340_state',
 			'wc_update_340_last_active',
 			'wc_update_340_db_version',
 		),
-		'3.4.3'  => array(
+		'3.4.3'    => array(
 			'wc_update_343_cleanup_foreign_keys',
 			'wc_update_343_db_version',
 		),
-		'3.4.4'  => array(
+		'3.4.4'    => array(
 			'wc_update_344_recreate_roles',
 			'wc_update_344_db_version',
 		),
-		'3.5.0'  => array(
+		'3.5.0'    => array(
 			'wc_update_350_reviews_comment_type',
 			'wc_update_350_db_version',
 		),
-		'3.5.2'  => array(
+		'3.5.2'    => array(
 			'wc_update_352_drop_download_log_fk',
 		),
-		'3.5.4'  => array(
+		'3.5.4'    => array(
 			'wc_update_354_modify_shop_manager_caps',
 			'wc_update_354_db_version',
 		),
-		'3.6.0'  => array(
+		'3.6.0'    => array(
 			'wc_update_360_product_lookup_tables',
 			'wc_update_360_term_meta',
 			'wc_update_360_downloadable_product_permissions_index',
 			'wc_update_360_db_version',
 		),
-		'3.7.0'  => array(
+		'3.7.0'    => array(
 			'wc_update_370_tax_rate_classes',
 			'wc_update_370_mro_std_currency',
 			'wc_update_370_db_version',
 		),
-		'3.9.0'  => array(
+		'3.9.0'    => array(
 			'wc_update_390_move_maxmind_database',
 			'wc_update_390_change_geolocation_database_update_cron',
 			'wc_update_390_db_version',
 		),
-		'4.0.0'  => array(
+		'4.0.0'    => array(
 			'wc_update_product_lookup_tables',
 			'wc_update_400_increase_size_of_column',
 			'wc_update_400_reset_action_scheduler_migration_status',
@@ -176,27 +176,27 @@ class WC_Install {
 			'wc_admin_update_0251_remove_unsnooze_action',
 			'wc_update_400_db_version',
 		),
-		'4.4.0'  => array(
+		'4.4.0'    => array(
 			'wc_update_440_insert_attribute_terms_for_variable_products',
 			'wc_admin_update_110_remove_facebook_note',
 			'wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note',
 			'wc_update_440_db_version',
 		),
-		'4.5.0'  => array(
+		'4.5.0'    => array(
 			'wc_update_450_sanitize_coupons_code',
 			'wc_update_450_db_version',
 		),
-		'5.0.0'  => array(
+		'5.0.0'    => array(
 			'wc_update_500_fix_product_review_count',
 			'wc_admin_update_160_remove_facebook_note',
 			'wc_admin_update_170_homescreen_layout',
 			'wc_update_500_db_version',
 		),
-		'5.6.0'  => array(
+		'5.6.0'    => array(
 			'wc_update_560_create_refund_returns_page',
 			'wc_update_560_db_version',
 		),
-		'6.0.0'  => array(
+		'6.0.0'    => array(
 			'wc_update_600_migrate_rate_limit_options',
 			'wc_admin_update_270_delete_report_downloads',
 			'wc_admin_update_271_update_task_list_options',
@@ -205,130 +205,132 @@ class WC_Install {
 			'wc_admin_update_290_delete_default_homepage_layout_option',
 			'wc_update_600_db_version',
 		),
-		'6.3.0'  => array(
+		'6.3.0'    => array(
 			'wc_update_630_create_product_attributes_lookup_table',
 			'wc_admin_update_300_update_is_read_from_last_read',
 			'wc_update_630_db_version',
 		),
-		'6.4.0'  => array(
+		'6.4.0'    => array(
 			'wc_update_640_add_primary_key_to_product_attributes_lookup_table',
 			'wc_admin_update_340_remove_is_primary_from_note_action',
 			'wc_update_640_db_version',
 		),
-		'6.5.0'  => array(
+		'6.5.0'    => array(
 			'wc_update_650_approved_download_directories',
 		),
-		'6.5.1'  => array(
+		'6.5.1'    => array(
 			'wc_update_651_approved_download_directories',
 		),
-		'6.7.0'  => array(
+		'6.7.0'    => array(
 			'wc_update_670_purge_comments_count_cache',
 			'wc_update_670_delete_deprecated_remote_inbox_notifications_option',
 		),
-		'7.0.0'  => array(
+		'7.0.0'    => array(
 			'wc_update_700_remove_download_log_fk',
 			'wc_update_700_remove_recommended_marketing_plugins_transient',
 		),
-		'7.2.1'  => array(
+		'7.2.1'    => array(
 			'wc_update_721_adjust_new_zealand_states',
 			'wc_update_721_adjust_ukraine_states',
 		),
-		'7.2.2'  => array(
+		'7.2.2'    => array(
 			'wc_update_722_adjust_new_zealand_states',
 			'wc_update_722_adjust_ukraine_states',
 		),
-		'7.5.0'  => array(
+		'7.5.0'    => array(
 			'wc_update_750_add_columns_to_order_stats_table',
 			'wc_update_750_disable_new_product_management_experience',
 		),
-		'7.7.0'  => array(
+		'7.7.0'    => array(
 			'wc_update_770_remove_multichannel_marketing_feature_options',
 		),
-		'7.9.0'  => array(
+		'7.9.0'    => array(
 			'wc_update_790_blockified_product_grid_block',
 		),
-		'8.1.0'  => array(
+		'8.1.0'    => array(
 			'wc_update_810_migrate_transactional_metadata_for_hpos',
 		),
-		'8.3.0'  => array(
+		'8.3.0'    => array(
 			'wc_update_830_rename_checkout_template',
 			'wc_update_830_rename_cart_template',
 		),
-		'8.6.0'  => array(
+		'8.6.0'    => array(
 			'wc_update_860_remove_recommended_marketing_plugins_transient',
 		),
-		'8.7.0'  => array(
+		'8.7.0'    => array(
 			'wc_update_870_prevent_listing_of_transient_files_directory',
 		),
-		'8.9.0'  => array(
+		'8.9.0'    => array(
 			'wc_update_890_update_connect_to_woocommerce_note',
 			'wc_update_890_update_paypal_standard_load_eligibility',
 		),
-		'8.9.1'  => array(
+		'8.9.1'    => array(
 			'wc_update_891_create_plugin_autoinstall_history_option',
 		),
-		'9.1.0'  => array(
+		'9.1.0'    => array(
 			'wc_update_910_add_launch_your_store_tour_option',
 			'wc_update_910_remove_obsolete_user_meta',
 		),
-		'9.2.0'  => array(
+		'9.2.0'    => array(
 			'wc_update_920_add_wc_hooked_blocks_version_option',
 		),
-		'9.3.0'  => array(
+		'9.3.0'    => array(
 			'wc_update_930_add_woocommerce_coming_soon_option',
 			'wc_update_930_migrate_user_meta_for_launch_your_store_tour',
 		),
-		'9.4.0'  => array(
+		'9.4.0'    => array(
 			'wc_update_940_add_phone_to_order_address_fts_index',
 			'wc_update_940_remove_help_panel_highlight_shown',
 		),
-		'9.5.0'  => array(
+		'9.5.0'    => array(
 			'wc_update_950_tracking_option_autoload',
 		),
-		'9.6.1'  => array(
+		'9.6.1'    => array(
 			'wc_update_961_migrate_default_email_base_color',
 		),
-		'9.8.0'  => array(
+		'9.8.0'    => array(
 			'wc_update_980_remove_order_attribution_install_banner_dismissed_option',
 		),
-		'9.8.5'  => array(
+		'9.8.5'    => array(
 			'wc_update_985_enable_new_payments_settings_page_feature',
 		),
-		'9.9.0'  => array(
+		'9.9.0'    => array(
 			'wc_update_990_remove_wc_count_comments_transient',
 			'wc_update_990_remove_email_notes',
 		),
-		'10.0.0' => array(
+		'10.0.0'   => array(
 			'wc_update_1000_multisite_visibility_setting',
 			'wc_update_1000_remove_patterns_toolkit_transient',
 		),
-		'10.2.0' => array(
+		'10.2.0'   => array(
 			'wc_update_1020_add_old_refunded_order_items_to_product_lookup_table',
 		),
-		'10.3.0' => array(
+		'10.3.0'   => array(
 			'wc_update_1030_add_comments_date_type_index',
 		),
-		'10.4.0' => array(
+		'10.4.0'   => array(
 			'wc_update_1040_add_idx_date_paid_status_parent',
 			'wc_update_1040_cleanup_legacy_ptk_patterns_fetching',
 		),
-		'10.5.0' => array(
+		'10.5.0'   => array(
 			'wc_update_1050_migrate_brand_permalink_setting',
 			'wc_update_1050_enable_autoload_options',
 			'wc_update_1050_add_idx_user_email',
 			'wc_update_1050_remove_deprecated_marketplace_option',
 		),
-		'10.6.0' => array(
+		'10.6.0'   => array(
 			'wc_update_1060_add_woo_idx_comment_approved_type_index',
 		),
-		'10.7.0' => array(
+		'10.7.0'   => array(
 			'wc_update_1070_disable_hpos_sync_on_read',
 		),
-		'10.8.0' => array(
+		'10.8.0'   => array(
 			'wc_update_1080_migrate_analytics_import_option',
-			'wc_update_1080_slim_orders_meta_key_index',
 			'wc_update_1080_backfill_email_template_sync_meta',
 		),
+		'10.8.0-2' => array(
+			'wc_update_10802_restore_orders_meta_key_value_index',
+		),
 	);

 	/**
@@ -579,7 +581,8 @@ class WC_Install {
 	 * @return void
 	 */
 	public static function install_actions() {
-		if ( ! empty( $_GET['do_update_woocommerce'] ) ) { // WPCS: input var ok.
+		if ( ! empty( $_GET['do_update_woocommerce'] ) ) {
+			// WPCS: input var ok.
 			check_admin_referer( 'wc_db_update', 'wc_db_update_nonce' );
 			wc_get_logger()->info( 'Manual database update triggered.', array( 'source' => 'wc-updater' ) );
 			self::update();
@@ -602,7 +605,8 @@ class WC_Install {
 				}

 				$return_url = esc_url_raw( wp_unslash( $return_url ) );
-				wp_safe_redirect( $return_url ); // WPCS: input var ok.
+				wp_safe_redirect( $return_url );
+				// WPCS: input var ok.
 				exit;
 			}
 		}
diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php
index 3648be5bb37..a06659c8487 100644
--- a/plugins/woocommerce/includes/wc-update-functions.php
+++ b/plugins/woocommerce/includes/wc-update-functions.php
@@ -3463,39 +3463,62 @@ function wc_update_1080_migrate_analytics_import_option(): void {
 }

 /**
- * Slim the `meta_key_value` index on `wc_orders_meta` by removing the `meta_value` column.
- *
- * The original composite index `(meta_key(100), meta_value(82))` overlaps heavily with
- * `order_id_meta_key_meta_value` and the `meta_value` prefix adds significant storage
- * overhead with negligible selectivity benefit. All core queries that use this index
- * filter primarily by `meta_key`.
+ * Reshape the `meta_key_value` index on `wc_orders_meta` to `(meta_key(50), meta_value(20))`.
+ *
+ * This is labeled as a 10.8.0-2 migration because originally there was a 10.8 migration that modified the
+ * meta_key_value index to include only the meta_key column (see https://github.com/woocommerce/woocommerce/pull/63897),
+ * but later it was discovered that this caused performance issues (as commented in the same pull request),
+ * so this new migration was added. However sites where 10.8 beta was installed will already have run
+ * the original migration (the one that removed meta_value from the index) and will have their db
+ * version updated to 10.8, so this new migration wouldn't run. Hence the 10.8.0-2 marker, which
+ * sorts between 10.8.0 and 10.8.1 via version_compare() and leaves the 10.8.1 slot free for any
+ * future patch-release migrations. WooCommerce 10.8.0 beta 2 had a migration labeled as 10.8.0-1 already,
+ * hence the need to go with 10.8.0-2 for this one.
+ *
+ * Handles two starting states transparently:
+ *  - Pre-10.8 sites: the index is the original `(meta_key(100), meta_value(82))`.
+ *  - 10.8 beta sites: the index has been changed to `(meta_key(100))` only.
+ *
+ * The new prefixes are sized from profiling a production-scale table: all meta_keys fit
+ * within 47 chars (so `meta_key(50)` covers every existing key) and a 20-byte `meta_value`
+ * prefix preserves full selectivity for the affected query patterns, keeping most of the
+ * storage benefit of the slim attempt.
  *
  * @since 10.8.0
  *
  * @return void
  */
-function wc_update_1080_slim_orders_meta_key_index(): void {
+function wc_update_10802_restore_orders_meta_key_value_index(): void {
 	global $wpdb;

 	$table_name = $wpdb->prefix . 'wc_orders_meta';
 	$index_name = 'meta_key_value';

 	// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
-	$index = $wpdb->get_row(
+	$columns = $wpdb->get_results(
 		$wpdb->prepare(
-			'SHOW INDEX FROM ' . $table_name . ' WHERE Key_name = %s AND Column_name = %s',
-			$index_name,
-			'meta_value'
+			'SHOW INDEX FROM ' . $table_name . ' WHERE Key_name = %s',
+			$index_name
 		)
 	);
 	// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared

-	if ( is_null( $index ) ) {
+	$already_correct =
+		is_array( $columns ) && 2 === count( $columns ) &&
+		'meta_key' === $columns[0]->Column_name && 50 === (int) $columns[0]->Sub_part &&
+		'meta_value' === $columns[1]->Column_name && 20 === (int) $columns[1]->Sub_part;
+
+	if ( $already_correct ) {
 		return;
 	}

-	// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
-	$wpdb->query( "ALTER TABLE {$table_name} DROP INDEX {$index_name}, ADD INDEX {$index_name} (meta_key(100))" );
+	if ( empty( $columns ) ) {
+		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+		$wpdb->query( "ALTER TABLE {$table_name} ADD INDEX {$index_name} (meta_key(50), meta_value(20))" );
+	} else {
+		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+		$wpdb->query( "ALTER TABLE {$table_name} DROP INDEX {$index_name}, ADD INDEX {$index_name} (meta_key(50), meta_value(20))" );
+	}
 }

 /**
diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
index ee7ef61dd38..f32af8c65ac 100644
--- a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
+++ b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
@@ -3395,7 +3395,7 @@ CREATE TABLE $meta_table (
 	order_id bigint(20) unsigned null,
 	meta_key varchar(255),
 	meta_value text null,
-	KEY meta_key_value (meta_key(100)),
+	KEY meta_key_value (meta_key(50), meta_value(20)),
 	KEY order_id_meta_key_meta_value (order_id, meta_key(100), meta_value($composite_meta_value_index_length))
 ) $collate;
 ";