EAV Load and Save Processes in Magento 2

Aug 21, 2018221Igor Rain
EAV Load and Save Processes in Magento 2

The Magento\Framework\EntityManager\EntityManager class was introduced in Magento 2.1 for loading, saving, checking for presence and deleting EAV and Flat objects. To work via EntityManager, you must provide the information about the entity interface in the di.xml file for MetadataPool and for HydratorPool.

The Magento\Framework\EntityManager\OperationPool class contains an array of operations that invoke the EntityManager to perform loading, saving, checking for presence, and deleting an object. The operation is executed by the execute method.

Default operations:

checkIfExists — Magento\Framework\EntityManager\Operation\CheckIfExists;

read — Magento\Framework\EntityManager\Operation\Read;

create — Magento\Framework\EntityManager\Operation\Create;

update — Magento\Framework\EntityManager\Operation\Update;

delete — Magento\Framework\EntityManager\Operation\Delete.

The CheckIfExists operation checks by default the presence of a record in the main table using a direct SQL query.

The Read operation performs 3 sub-operations by default:

  • ReadMain
  • ReadAttributes
  • ReadExtensions

The Create operation performs 3 sub-operations by default:

  • CreateMain
  • CreateAttributes
  • CreateExtensions

The Update operation performs 3 sub-operations by default:

  • UpdateMain
  • UpdateAttributes
  • UpdateExtensions

The Delete operation performs 3 sub-operations by default (in the reverse order):

  • DeleteExtensions
  • DeleteAttributes
  • DeleteMain

The operations for working with attributes are located in the Magento\Framework\EntityManager\Operation\AttributePool class.

With the help of overrides on attribute operations, EAV uses the following classes for operations:

  • Magento\Eav\Model\ResourceModel\CreateHandler
  • Magento\Eav\Model\ResourceModel\UpdateHandler
  • Magento\Eav\Model\ResourceModel\ReadHandler

CreateHandler writes the attribute values to the new entity.

UpdateHandler takes a snapshot using ReadSnapshot (which is based on ReadHandler). Next:

  • it changes the value if the attribute is changed relative to Snapshot and the new value is not empty or the attribute allows null values;
  • deletes if the attribute has been changed relative to Snapshot and the new value is null and the attribute does not allow null values;
  • creates if the attribute is absent in Snapshot and the new value is not null or the attribute allows null values.

ReadHandler executes the reading according to the following algorithm:

  1. Gets all the attribute tables for a particular entity_type.
  2. Performs the following for each table:
    1. select subquery is created from the current table, which requests value and attribute_id;
    2. a condition is added that entity_id = ID of the requested entity;
    3. a condition is added for each scope from the context that store_id IN ($scope->getValue());
    4. sorts by store_id in descending order.
  3. Does UNION ALL of all the subqueries.
  4. Executes the SQL query.
  5. Writes the received values to the $entityData array.

What happens when an EAV entity has too many attributes

The advantage of EAV over Flat is that a Flat table in InnoDb can contain no more than 1017 columns. In EAV, the number of attributes is limited only by the maximum size of innodb tables.

How the number of websites/stores affects the EAV load/save process

The number of websites/stores affects the loading/saving of an entity.

Let’s see how a number of websites/stores affect the loading and saving of attributes.

The Magento scope in EAV is implemented using the store_id column in the EAV attribute value tables.

  • store_id = 0, if the scope is global;
  • store_id = ID of the chosen Store View, if not global.

Loading of attribute values happens as follows:

  • store_id IN (STORE_IDS), where STORE_IDS — Store View identifiers of the current context.

The context is evaluated recursively:

The identifier of the current scope is added to the STORE_IDS array.

If there is a Fallback scope in the current scope, then the operation is repeated for Fallback.

Example: store_id = 5 specifies fallback as 3, and 3 specifies fallback as 0. Then STORE_IDS will be: [5, 3, 0].

In most cases, the standard scope provider Magento\Store\Model\StoreScopeProvider is used.

It works as follows:

  • The store_id is specified as an identifier of the current Store View;
  • If the current store_id!= 0, then it adds a fallback as 0.

It turns out that the number of websites/stores does not directly* affect the loading speed, because when loaded using the StoreScopeProvider, the context contains no more than two store_id, i.e. does not depend on the number of websites/stores.

* the number of websites/stores always affects indirectly the loading of attribute values, since the more rows there are in the attribute value tables, the slower is the download.

Let’s consider the value of store_id when saving the attribute value.

Attribute scope All Store Views Particular Store View
global store_id = 0 store_id = 0
website store_id = 0 records for each Store View of this Website are created / changed
store view store_id = 0 store_id = ID Store View

Thus, the speed of storing an attribute, depending on the number of websites/stores, is affected by the presence of the changed attributes from the scope website. The more Store Views there are in the Website, the more necessary it is to create or change records in the database, the slower is the saving.

How to customize the load and save process for an EAV entity in the situations described here

To override operations, add the following to di.xml:

You can perform a partial override, for example, of only one read operation, then the default operations will be used instead of the rest operations.

You can also override the operations of working with attributes for EAV:

Overriding the Extensions:

 



Post a new comment

top
BelVG Newsletter
Subscribe to our mailing list and get interesting stuff and updates to your email inbox.
Email *