We have over 1200 attributes sets. Every time we make a change to an attribute set, it takes about 5 minutes to save. We have indexing set to Manual. I'm not sure what else we can do to speed this up. Any suggestions?
1 Answer
I took a default installation and ran a Blackfire.io test on the save action of the attribute set page. This is the main method I found that takes the bulk of the time Mage_Eav_Model_Resource_Entity_Attribute_Group::_afterSave
This is what the _afterSave
function looks like;
protected function _afterSave(Mage_Core_Model_Abstract $object)
{
if ($object->getAttributes()) {
foreach ($object->getAttributes() as $attribute) {
$attribute->setAttributeGroupId($object->getId());
$attribute->save();
}
}
return parent::_afterSave($object);
}
If I comment out the foreach part of the function, the time it takes to process the above result drops from 3.99 seconds to 118 milliseconds. So that is the part that really takes the largest amount of time.
It saves every attribute, even though the value might not even have changed. We'll add a database call that will find each attribute group each attribute is in, and then check if it already exists. If it doesn't, it'll be added. If it does exist, we'll check if the value has changed. If it has, we'll update the attribute. This will dramatically cut down the time needed.
So replace the method with this method (be sure to test this thoroughly on your test environment first, side-effects may occur);
protected function _afterSave(Mage_Core_Model_Abstract $object)
{
$resource = Mage::getModel('core/resource');
$db = $resource->getConnection('core_read');
$attributeGroups = $db->fetchPairs('SELECT attribute_id,attribute_group_id FROM eav_entity_attribute');
if ($object->getAttributes()) {
foreach ($object->getAttributes() as $attribute) {
if(
(isset($attributeGroups[$attribute->getId()]) && $attributeGroups[$attribute->getId()] != $object->getId())
||
!isset($attributeGroups[$attribute->getId()])
) {
$attribute->setAttributeGroupId($object->getId());
$attribute->save();
}
}
}
return parent::_afterSave($object);
}
This drops the processing speed from 3.99s to 145ms in my case.
Of course, you should adhere to Magento best practices and create an extension that extends this model where you apply the custom code.
-
2