Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix duplicate queries in product grids #4695 #5002

Merged
merged 4 commits into from Nov 4, 2021

Conversation

mikejolley
Copy link
Member

@mikejolley mikejolley commented Oct 26, 2021

Adds caching (and cache priming) to the product grid to prevent duplicate queries.

Fixes #4695

The issue here was the get_variations method in the ProductSchema class queries all product variations per product, and that custom query is uncached. If the same product is queried multiple times (for instance, if showing multiple product grids) the query will repeat. This results in duplicate queries.

To test this, I added 2 product grids to a page, both containing variable products. This is an example from Query Monitor:

Screenshot 2021-10-27 at 12 14 00
Screenshot 2021-10-27 at 12 13 48

Notice (1), there are 2 calls to each set of variations (duplicate queries). This needs fixing with cache.

Notice (2), there is a separate query for each variable product. This is expected, but could be fixed by priming the cache.

This PR implements both. A cache for each products $variation_meta_data query (1), and a cache priming function once the results of the product grid query are returned (2). This eliminates duplicate queries, and reduces the overall total number of queries on the page:

Screenshot 2021-10-27 at 12 16 49

Testing

User facing:

  1. Add multiple product grid blocks to a page e.g. Products by Category. Ensure there are some variable products visible, or add some new ones
  2. Check the Grid Block renders correctly on the frontend.

Dev:

  1. Install Query Monitor
  2. Check the total number of queries for the above scenario before and after this patch
  3. Confirm total number of queries is reduced and there are no duplicate queries for this grid block shown in query monitor
  4. Make an API request to a variable product by ID, e.g. https://store.local/wp-json/wc/store/products/11. Confirm the variations section is still populated.

Changelog

Improved performance of Product Grid Blocks and Products Store API endpoint by caching product variations.

@mikejolley mikejolley added the focus: performance The issue/PR is related to performance. label Oct 26, 2021
@mikejolley mikejolley self-assigned this Oct 26, 2021
@rubikuserbot rubikuserbot requested review from a team and opr and removed request for a team October 26, 2021 20:07
@github-actions
Copy link
Contributor

github-actions bot commented Oct 26, 2021

Size Change: +8.31 kB (+1%)

Total Size: 1.11 MB

Filename Size Change
build/active-filters-frontend.js 8.18 kB -149 B (-2%)
build/active-filters.js 8.01 kB -3 B (0%)
build/all-products-frontend.js 23.1 kB -161 B (-1%)
build/all-products.js 38 kB +145 B (0%)
build/atomic-block-components/add-to-cart--atomic-block-components/button--atomic-block-components/image---a7e2bb9b.js 3.19 kB -2 B (0%)
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 1.81 kB -1 B (0%)
build/atomic-block-components/add-to-cart--atomic-block-components/image--atomic-block-components/title.js 0 B -332 B (removed) 🏆
build/atomic-block-components/add-to-cart-frontend.js 8.34 kB -170 B (-2%)
build/atomic-block-components/add-to-cart.js 7.85 kB +10 B (0%)
build/atomic-block-components/button-frontend.js 1.74 kB -3 B (0%)
build/atomic-block-components/button.js 875 B +1 B (0%)
build/atomic-block-components/category-list-frontend.js 467 B +3 B (+1%)
build/atomic-block-components/category-list.js 469 B -1 B (0%)
build/atomic-block-components/image-frontend.js 1.71 kB -173 B (-9%)
build/atomic-block-components/image.js 1.36 kB +13 B (+1%)
build/atomic-block-components/price-frontend.js 2.13 kB -3 B (0%)
build/atomic-block-components/price.js 2.11 kB +2 B (0%)
build/atomic-block-components/rating-frontend.js 563 B +2 B (0%)
build/atomic-block-components/rating.js 565 B -1 B (0%)
build/atomic-block-components/sale-badge-frontend.js 861 B +2 B (0%)
build/atomic-block-components/sku-frontend.js 391 B -1 B (0%)
build/atomic-block-components/summary.js 912 B +1 B (0%)
build/atomic-block-components/tag-list-frontend.js 467 B +1 B (0%)
build/atomic-block-components/title-frontend.js 1.48 kB -76 B (-5%)
build/atomic-block-components/title.js 1.48 kB +97 B (+7%) 🔍
build/attribute-filter-frontend.js 18.1 kB -175 B (-1%)
build/attribute-filter.js 12.1 kB -3 B (0%)
build/blocks-checkout.js 21 kB -22 B (0%)
build/cart-blocks/accepted-payment-methods-frontend.js 1.39 kB -2 B (0%)
build/cart-blocks/checkout-button-frontend.js 1.22 kB -22 B (-2%)
build/cart-blocks/express-payment--checkout-blocks/express-payment--checkout-blocks/payment-frontend.js 4.73 kB +7 B (0%)
build/cart-blocks/express-payment-frontend.js 1.58 kB -5 B (0%)
build/cart-blocks/filled-cart-frontend.js 806 B -2 B (0%)
build/cart-blocks/line-items-frontend.js 5.85 kB +45 B (+1%)
build/cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 3.69 kB +1 B (0%)
build/cart-blocks/order-summary-frontend.js 7.4 kB -16 B (0%)
build/cart-frontend.js 52.2 kB -631 B (-1%)
build/cart.js 50.5 kB +26 B (0%)
build/checkout-blocks/actions-frontend.js 1.48 kB -26 B (-2%)
build/checkout-blocks/billing-address-frontend.js 2.64 kB -24 B (-1%)
build/checkout-blocks/contact-information-frontend.js 3.87 kB -22 B (-1%)
build/checkout-blocks/express-payment-frontend.js 1.93 kB +1 B (0%)
build/checkout-blocks/fields-frontend.js 346 B -1 B (0%)
build/checkout-blocks/order-note-frontend.js 1.56 kB -2 B (0%)
build/checkout-blocks/order-summary-frontend.js 12.8 kB +55 B (0%)
build/checkout-blocks/payment-frontend.js 4.56 kB -28 B (-1%)
build/checkout-blocks/shipping-address-frontend.js 3.03 kB -23 B (-1%)
build/checkout-blocks/shipping-methods-frontend.js 5.54 kB -20 B (0%)
build/checkout-blocks/terms-frontend.js 1.65 kB -2 B (0%)
build/checkout-blocks/totals-frontend.js 329 B -1 B (0%)
build/checkout-frontend.js 54.4 kB -688 B (-1%)
build/checkout.js 54 kB +17 B (0%)
build/featured-category.js 7.74 kB +1 B (0%)
build/featured-product.js 9.42 kB -6 B (0%)
build/handpicked-products.js 6.27 kB +4 B (0%)
build/mini-cart-component-frontend.js 44.4 kB +7.45 kB (+20%) 🚨
build/mini-cart-frontend.js 2.33 kB +5 B (0%)
build/mini-cart.js 5.72 kB +434 B (+8%) 🔍
build/price-filter-frontend.js 14.2 kB -197 B (-1%)
build/price-filter.js 9.65 kB -5 B (0%)
build/product-best-sellers.js 6.62 kB -8 B (0%)
build/product-category.js 7.49 kB -2 B (0%)
build/product-new.js 6.77 kB -8 B (0%)
build/product-on-sale.js 7.11 kB -16 B (0%)
build/product-search.js 2.68 kB +3 B (0%)
build/product-tag.js 6.6 kB +9 B (0%)
build/product-top-rated.js 6.74 kB -5 B (0%)
build/products-by-attribute.js 7.7 kB -3 B (0%)
build/reviews-by-category.js 11.4 kB -10 B (0%)
build/reviews-by-product.js 13 kB -10 B (0%)
build/reviews-frontend.js 8.97 kB +10 B (0%)
build/single-product-frontend.js 26.6 kB +8 B (0%)
build/single-product.js 9.75 kB -18 B (0%)
build/stock-filter-frontend.js 8.62 kB -142 B (-2%)
build/stock-filter.js 7.81 kB -8 B (0%)
build/vendors--atomic-block-components/add-to-cart-frontend.js 4.77 kB -6 B (0%)
build/vendors--cart-blocks/line-items--checkout-blocks/order-summary-frontend.js 3.14 kB +36 B (+1%)
build/wc-blocks-editor-style-rtl.css 15.7 kB +98 B (+1%)
build/wc-blocks-editor-style.css 15.7 kB +101 B (+1%)
build/wc-blocks-middleware.js 1.19 kB -282 B (-19%) 👏
build/wc-blocks-registry.js 3.71 kB +1 B (0%)
build/wc-blocks-shared-context.js 1.54 kB -5 B (0%)
build/wc-blocks-shared-hocs.js 1.92 kB +172 B (+10%) ⚠️
build/wc-blocks-style-rtl.css 21 kB +399 B (+2%)
build/wc-blocks-style.css 21 kB +401 B (+2%)
build/wc-blocks-vendors.js 254 kB +157 B (0%)
build/wc-blocks.js 3.49 kB -1 B (0%)
build/wc-settings.js 2.91 kB -1 B (0%)
build/legacy-template.js 2.12 kB +2.12 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size
build/all-reviews.js 9.57 kB
build/atomic-block-components/sale-badge.js 868 B
build/atomic-block-components/sku.js 393 B
build/atomic-block-components/stock-indicator-frontend.js 611 B
build/atomic-block-components/stock-indicator.js 611 B
build/atomic-block-components/summary-frontend.js 908 B
build/atomic-block-components/tag-list.js 471 B
build/cart-blocks/empty-cart-frontend.js 349 B
build/cart-blocks/items-frontend.js 303 B
build/cart-blocks/totals-frontend.js 322 B
build/price-format.js 1.37 kB
build/product-categories.js 3.37 kB
build/vendors--atomic-block-components/add-to-cart--cart-blocks/order-summary--checkout-blocks/billing-ad--c5eb4dcd-frontend.js 16.1 kB
build/vendors--atomic-block-components/price--cart-blocks/line-items--cart-blocks/order-summary--checkout--8a3571de-frontend.js 5.71 kB
build/vendors--cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/order-summary---eb4d2cec-frontend.js 5.02 kB
build/wc-blocks-data.js 11.3 kB
build/wc-blocks-google-analytics.js 1.98 kB
build/wc-blocks-vendors-style-rtl.css 1.37 kB
build/wc-blocks-vendors-style.css 1.37 kB
build/wc-payment-method-bacs.js 806 B
build/wc-payment-method-cheque.js 806 B
build/wc-payment-method-cod.js 898 B
build/wc-payment-method-paypal.js 839 B
build/wc-payment-method-stripe.js 12.2 kB

compressed-size-action

@mikejolley mikejolley added this to the 6.3.0 milestone Oct 27, 2021
@mikejolley mikejolley marked this pull request as ready for review October 27, 2021 11:21
Copy link
Contributor

@opr opr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This solves the problem and the code looks solid, couple of non-blocking queries though which you can feel free to ignore or action.

global $wpdb;

// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$product_variations = $wpdb->get_results( "SELECT ID as variation_id, post_parent as product_id from {$wpdb->posts} WHERE post_parent IN ( " . implode( ',', $prime_product_ids ) . ' )', ARRAY_A );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering why prime_variation_ids in the next query is run through esc_sql but this one isn't.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one has been ran through wp_parse_id_list. $prime_variation_ids is from the results of the first query.

Comment on lines 631 to 635
// Whilst the query above only includes keys of $default_variation_meta_data, the cache may have been
// primed elsewhere.
if ( in_array( $data->attribute_key, $default_variation_meta_keys, true ) ) {
$values[ $data->variation_id ][ $data->attribute_key ] = $data->attribute_value;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me quite a while to understand what this check was for, even in spite of the comment. Could you expand on the comment a little bit to give more context? (Feel free to disagree if you think it's just me, though!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the context of this function, we have $default_variation_meta_keys so we know all the values are relevant. The cache prime function I wrote however may have other keys outside of $default_variation_meta_keys e.g. attributes from over variable products. Does that sort of make sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it does, thanks Mike 👍🏼

@mikejolley mikejolley merged commit 7329935 into trunk Nov 4, 2021
@mikejolley mikejolley deleted the fix/duplicate-query-caching-4695 branch November 4, 2021 11:39
@nielslange nielslange changed the title Fix Duplicate Queries in Product Grids #4695 Fix duplicate queries in product grids #4695 Nov 15, 2021
@nielslange nielslange added the type: enhancement The issue is a request for an enhancement. label Nov 15, 2021
jonny-bull pushed a commit to jonny-bull/woocommerce-gutenberg-products-block that referenced this pull request Dec 14, 2021
…5002)

* Cache variation_meta_data to prevent duplicate queries with multiple grids

* Prime the cache

* Improve existing cache detection

* Expand comment
jonny-bull pushed a commit to jonny-bull/woocommerce-gutenberg-products-block that referenced this pull request Dec 16, 2021
…5002)

* Cache variation_meta_data to prevent duplicate queries with multiple grids

* Prime the cache

* Improve existing cache detection

* Expand comment
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
focus: performance The issue/PR is related to performance. type: enhancement The issue is a request for an enhancement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Experimental tracking support data for impressions causing slowdown
3 participants