Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache all attribute options for display in layered navigation #943 #942

Merged
merged 2 commits into from
Jun 26, 2020

Conversation

rvelhote
Copy link
Contributor

@rvelhote rvelhote commented May 1, 2020

Related to issue #934.

This will improve performance by reducing the amount of SQL Queries when fetching all possible attributes to display in the layered navigation. The amount of queries you will save is related to the amount of attributes you each store has configured to be available for layered navigation.

When saving attributes Magento will clear the translate cache tag so that cache tag as well as the EAV cache tag are included with this cache object.

This will improve performance by reducing the amount of SQL Queries when fetching all possible attributes to display in the layered navigation
@colinmollenhour
Copy link
Member

I may be missing something, but you do not need to add the translate cache tag because updating translations will not have a material affect on the attribute options.

You should add the individual id tag as well to be safe. So the final $tags = line can be:

            $tags = array_merge(['eav'], $this->getAttribute()->getCacheTags());

@rvelhote
Copy link
Contributor Author

rvelhote commented May 6, 2020

I included the translate cache tag because Magento also clears it after saving an attribute (with the comment Clear translation cache because attribute labels are stored in translation). If the user updates the attribute with a new translation then no one would see it until the translation cache was cleared.

The suggestion you made to use $this->getAttribute()->getCacheTags() is much better and it also includes Mage_Eav_Model_Entity_Attribute::CACHE_TAG plus an attribute specific tag. I will update the PR.

@sreichel sreichel added enhancement performance Performance related work in progress For Pull Requests which still have changes planned Component: Eav Relates to Mage_Eav labels Jun 1, 2020
@rvelhote
Copy link
Contributor Author

I updated the PR to match @colinmollenhour suggestions.

I've been using this in production for a couple of months and works well in reducing the number of SQL queries. Of course it will hit the cache backend instead so if it's the database it's not much of a difference but if it's Redis or Memcached it will be better.

Copy link
Contributor

@sreichel sreichel left a comment

Choose a reason for hiding this comment

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

Already tested past days .... LGTM

@tmotyl
Copy link
Contributor

tmotyl commented Jun 24, 2020

Hi
I've took the patch for a little ride. Here are my findings:

  1. The SQL query we will avoid looks like:
SELECT `main_table`.*, `tdv`.`value` AS `default_value`, `tsv`.`value` AS `store_default_value`, IF(tsv.value_id > 0, tsv.value, tdv.value) AS `value` FROM `eav_attribute_option` AS `main_table`
 INNER JOIN `eav_attribute_option_value` AS `tdv` ON tdv.option_id = main_table.option_id
 LEFT JOIN `eav_attribute_option_value` AS `tsv` ON tsv.option_id = main_table.option_id AND tsv.store_id = '7' WHERE (`attribute_id` = '184') AND (tdv.store_id = 0) ORDER BY main_table.sort_order ASC, value ASC
  1. In my case on category page the $storeId = $this->getAttribute()->getStoreId(); was always null, which resulted in storing optionArray under empty string in $this->_options[$storeId].
    I recommend changing the line to:
$storeId = $this->getAttribute()->getStoreId();
if (is_null($storeId)) {
      $storeId = Mage::app()->getStore()->getId();
}

The same way it's done in setStoreFilter. This way it will be clear what is stored in $this->_options.
Anyway, to be honest I don't see how would one be able to change attribute store to have multiple store ids inside _options, but its another story.

  1. In my case I saw multiple calls to getAllOptions with the same attribute, so we might want to consider using a runtime cache too. I would be interested in getting feedback from you whether its also a case for you, or it depends on project customizations.

@colinmollenhour
Copy link
Member

@tmotyl A runtime cache usually makes sense because this will not be GCd in the lifetime of the request anyway and memory is cheap.

@rvelhote
Copy link
Contributor Author

@tmotyl I will add a local runtime cache. I only see one call for each attribute on my store so it might be something specific to your store.

@colinmollenhour colinmollenhour merged commit 19648fd into OpenMage:1.9.4.x Jun 26, 2020
@sreichel sreichel added this to the Release 19.4.6 milestone Jun 26, 2020
@sreichel sreichel removed the work in progress For Pull Requests which still have changes planned label Jun 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Eav Relates to Mage_Eav enhancement performance Performance related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants