Magento 2

Magento 2 Image Resizing Bottleneck: Unmasking the Hidden Index That's Slowing Your Store

Comparison of slow full table scan versus fast indexed database query in Magento
Comparison of slow full table scan versus fast indexed database query in Magento

Magento 2 Image Resizing Bottleneck: Unmasking the Hidden Index That's Slowing Your Store

As e-commerce migration experts at Shopping Mover, we're constantly delving into the intricate mechanics of Magento 2 to uncover and resolve performance bottlenecks. A recent deep dive into a critical GitHub issue (magento/magento2#41567) has brought to light a significant, yet often overlooked, database performance drain affecting on-demand image resizing. This issue, prevalent in Magento 2.4.x and impacting both Adobe Commerce and Open Source editions, reveals how a seemingly minor omission – a missing database index – can lead to severe performance degradation, especially for stores boasting extensive product catalogs.

For any Magento store, particularly those undergoing or planning a migration, understanding and addressing such core performance issues is paramount. Slow image loading directly impacts user experience, SEO rankings, and ultimately, conversion rates. Let's dissect this hidden culprit.

The Hidden Culprit: Full Catalogue Scans for Every Image Resize

The core of the problem lies within Magento's get.php script. This script is the unsung hero responsible for dynamically generating resized product images when a cached version doesn't exist. When a client (be it a shopper's browser or Googlebot-Image) requests an image that hasn't been resized to that specific dimension yet, get.php springs into action. This process involves a critical function call: Magento\Catalog\Model\ResourceModel\Product\Image::getRelatedWebsiteIds($filepath).

This function's purpose is to determine which websites an image is associated with, a necessary step when handling multi-website Magento installations. To achieve this, it executes a complex SQL query:

SELECT DISTINCTROW images.value AS filepath, GROUP_CONCAT(websites.website_id SEPARATOR ',') AS website_ids
FROM catalog_product_entity_media_gallery AS images
INNER JOIN catalog_product_entity_media_gallery_value AS image_value ON images.value_id = image_value.value_id
INNER JOIN catalog_product_entity AS products ON image_value.entity_id = products.entity_id
INNER JOIN catalog_product_website AS websites ON products.entity_id = websites.product_id
WHERE (images.disabled = 0 AND image_value.disabled = 0) AND (images.value = ?)
GROUP BY websites.product_id

The critical flaw in this otherwise logical query lies in the catalog_product_entity_media_gallery table. Despite the query explicitly filtering by images.value (the image file path), this crucial column lacks a database index. Without an index, the database optimizer is forced to perform a full table scan, effectively sifting through every single row in the catalog_product_entity_media_gallery table to find a match. This is akin to searching for a specific word in a dictionary without an alphabetical order – you have to read every page.

Real-World Impact: From Milliseconds to Minutes of Frustration

The impact of this missing index is far from theoretical. The issue author's production environment, with approximately 48,000 products and nearly 190,000 rows in catalog_product_entity_media_gallery, painted a stark picture:

  • High Call Volume: Over 158,000 calls to this query in just 11 days.
  • Excessive Query Time: An average query time of 290 ms, with peaks reaching 927 ms.
  • Massive Data Scans: Approximately 519,000 rows examined per call.
  • Significant Server Load: This single query accounted for a staggering 17.7% of all statement time on the server, making it the largest individual query by far.

Every one of these slow calls directly translates to a client waiting for an image to load. Whether it's a real shopper experiencing a sluggish page or Googlebot-Image struggling to index your product visuals, the cost in terms of user experience, SEO, and server resources is immense. For stores with even larger catalogs, these numbers would be exponentially worse, potentially crippling the site during peak traffic.

The Simple, Yet Powerful Solution: A Single Database Index

The beauty of this fix lies in its simplicity and profound impact. By merely adding an index to the value column of the catalog_product_entity_media_gallery table, the performance gains are dramatic. Benchmarks conducted on a copy of the table showed:

  • Without Index: p50 of 254.8 ms, p90 of 271.5 ms, max of 301.3 ms.
  • With INDEX(value): p50 of 0.7 ms, p90 of 0.8 ms, max of 1.1 ms.

That's a performance improvement of over 300x! After deploying this index in a production environment, live traffic saw average query times drop to 1.2 ms, with random paths hitting 0.4 ms. The cost? A mere ~10 MB for 189,000 rows, and the index builds online (INPLACE, LOCK=NONE) in under a second, minimizing downtime.

The fix involves adding a specific XML entry to Magento_Catalog's db_schema.xml, ensuring the index is properly managed by Magento's declarative schema system:

Broader Implications and Best Practices for Magento Performance

This case study underscores a fundamental principle of Magento 2 optimization: database indexing is not a luxury, but a necessity. While Magento's declarative schema system aims to manage indexes efficiently, oversights can occur, especially with new features or complex queries.

  • Proactive Monitoring: Regularly monitor your database performance, utilizing tools like performance_schema in MySQL/MariaDB, to identify slow queries. Don't wait for customer complaints.
  • Schema Awareness: Understand the structure of your core Magento tables and the queries that hit them most frequently. Any query filtering on a non-indexed column in a large table is a potential bottleneck.
  • Beyond Image Resizing: This specific index benefits any query filtering catalog_product_entity_media_gallery on its value column, such as duplicate image checks during imports or custom extensions.
  • Stay Updated: Keep your Magento installation updated with the latest patches and versions. Community contributions often address such performance issues.
  • Custom Module Fix: If an official patch isn't immediately available, consider implementing the index via a custom module's db_schema.xml to mitigate the issue in the interim.

For businesses considering a Magento migration or seeking to optimize their existing Adobe Commerce or Open Source store, identifying and resolving such deep-seated performance issues is crucial. At Shopping Mover, our expertise in Magento migrations extends to comprehensive performance audits, ensuring your new or optimized store runs at peak efficiency from day one. We help you navigate complex database structures, fine-tune configurations, and implement best practices to deliver a blazing-fast e-commerce experience.

Conclusion

The case of the missing index on catalog_product_entity_media_gallery.value serves as a powerful reminder that even seemingly minor database omissions can have a monumental impact on Magento 2 performance. By understanding the underlying mechanics and applying targeted optimizations, you can significantly enhance your store's speed, improve user experience, and boost your bottom line. Don't let hidden bottlenecks slow down your e-commerce success.

Share:

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools