Repository navigation
Conversation
Link\SaveHandler deleted every link of a product before saving the product's links again, so each product save deleted and re-inserted all of its related, up-sell, cross-sell and grouped links, even when none of them changed. Each save consumed new catalog_product_link ids and fired the mview triggers on that table, adding changelog rows for the catalog search, catalog rule, attribute, price and stock indexers. - SaveHandler now deletes only the links missing from the product's new link set. Kept links are saved through the link repository, which already updates an existing link in place. - Link::saveProductLinks() skips attribute values (position, grouped qty) that are already stored. INSERT ... ON DUPLICATE KEY UPDATE uses an auto increment id even when it only updates, so unchanged saves still consumed catalog_product_link_attribute_* ids. It also no longer sends a DELETE for an omitted attribute that has no stored value. A save that does not change a product's links now writes nothing to the catalog_product_link tables. Saves that add, remove, reorder or move links end with the same links as before.
Contributor
Author
|
@magento run all tests |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description (*)
Saving a product deletes all of its product links (related, up-sell, cross-sell, grouped) and inserts them again, even when none of them changed.
Product::afterSave()always callsLink\SaveHandler::execute(), which deleted every existing link before saving the product's link set. When no links are passed, that set is lazy-loaded from the database, so it is the same links.Each save therefore uses new
catalog_product_linkids and fires the mview triggers on that table. On a 2.4.7 store receiving frequent product updates over REST,catalog_product_link.link_idhad reached about 2.02 billion for 140k rows, and the changelogs fed by those triggers held billions of rows.SaveHandlerdeletes only the links that are no longer in the product's link set. Kept links go throughProductLinkRepository::save(), which already updates an existing link in place.Link::saveProductLinks()skips attribute values that are already stored.INSERT ... ON DUPLICATE KEY UPDATEuses an auto increment id even when it only updates, so unchanged saves still used upcatalog_product_link_attribute_*ids. An omitted attribute is only deleted when a value is stored.Measured over REST (
PUT /V1/products/:sku, indexers on Update by Schedule, a product with 6 links):product_linksin the payloadproduct_linkssent againThe changelog rows left after the change come from the product's own attributes.
link_idis now stable across saves, so code that relied on links being re-created on every save will see fewer deletes and inserts.Related Pull Requests
#41202 takes the same approach for custom options (#39652).
Fixed Issues (if relevant)
Manual testing scenarios (*)
bin/magento indexer:set-mode schedule.SELECT link_id, linked_product_id FROM catalog_product_link WHERE product_id = <A's id>, and the row count ofcatalogsearch_fulltext_cl.PUT /V1/products/Awith{"product": {"sku": "A", "price": 12}}.link_idvalues, and no changelog rows fromcatalog_product_link. Before this change, every link gets a newlink_id.PUT /V1/products/Awithproduct_linksfor B (position 2) and D. Expected: C's link is removed, D's is added, and B keeps itslink_idwith position 2.qtythroughproduct_links. Expected: the new qty is saved and both links keep theirlink_id.Questions or comments
Tested on MariaDB 10.6. Not tested on Adobe Commerce (
row_idand staging).Contribution checklist (*)