Magento 2 EAV: обзор структур данных

    В данной публикации я обзорно рассмотрю структуры данных Magento 2, поддерживающих функционирование такой концепции, как EAV. Разработчикам иногда нужно выбираться из дебрей кода и пытаться обозревать места своего жизнепровождения с высоты полёта орла — это позволяет наводить фокусы на вещи действительно важные или просто большие. Вот я и выбрался.


    image


    Аббревиатура EAV раскрывается как Entity-Attribute-Value (это для тех, кто не ходил по ссылке выше). Основной "плюшкой" EAV является эффективное использование пространства БД в тех случаях, когда возможное количество различных атрибутов (свойств, параметров), которые могут быть использованы для описания вещей (сущностей), является очень широким, но количество атрибутов, которое на самом деле относится к отдельному объекту, является относительно небольшим. Хорошим примером подобного случая в e-commerce служит такое понятие, как "продукт" — значимые атрибуты продуктов "телевизор" (размер экрана) отличаются от значимых атрибутов продуктов "спальный мешок" (минимальная комфортная температура).


    Так что же Magento 2 предлагает для хранения данных в формате EAV?


    'eav_' namespace


    В свежеразвёрнутой базе Magento 2.3 есть 21 таблица с префиксом eav_. Все их можно разделить на три группы:


    • eav_attribute
    • eav_entity
    • eav_form

    Проще всего с eav_form — эти таблицы относятся к отображению некоторых EAV-данных на UI и непосредственно к размещению EAV-данных в базе не относятся (я рассматриваю только структуры данных и только с точки зрения хранения информации, а не её отображения). Для эксперимента я удалил таблицы пространства eav_form из базы и это не помешало мне оформить заказ в магазине. Так что нужно ещё поискать, где используются данные из этого пространства таблиц и насколько они нужны для функционирования Magento.


    Из оставшихся двух группа eav_attribute относятся к букве A(ttribute), а группа eav_entity — к букве E(ntity). Где же буква V(alue)?


    Значения для атрибутов сущностей нужно искать в суффиксах имён таблиц:


    • _datetime
    • _decimal
    • _int
    • _text
    • _ varchar

    Можно видеть, что подобные суффиксы имеются у таблиц, начинающихся с:


    • catalog_category_entity_
    • catalog_product_entity_
    • customer_address_entity_
    • customer_entity_
    • eav_entity_

    Простое перемножение кол-ва суффиксов (5) на кол-во префиксов (5) даёт нам общее кол-во таблиц (25) в которых предполагается хранение values-данных.


    'eav_entity_type': реестр типов сущностей


    Начало EAV в Magento нужно искать в таблице eav_entity_type. Именно здесь задаётся, для каких типов сущностей значения атрибутов будут сохранятся в EAV-структуре. Так вот, изначально Magento 2.3 предлагает такой вариант для следующих восьми сущностей:


    • customer
    • customer_address
    • catalog_category
    • catalog_product
    • order
    • invoice
    • creditmemo
    • shipment

    'eav_attribute': реестр атрибутов


    Следующий шаг — находим, какими атрибутами могут характеризоваться эти типы сущностей. Данная информация находится в таблице eav_attribute. Реестр атрибутов имеет замыкание на реестр типов сущностей по внешнему ключу (foreign key). В реестре атрибутов изначально 135 записей, принадлежащих 4 типам сущностей:


    • customer
    • customer_address
    • catalog_category
    • catalog_product


      О чём это говорит? Ну, хотя бы о том, что остальные типы сущностей:


    • order
    • invoice
    • creditmemo
    • shipment

    не используют EAV-структуру для хранения данных. То есть, на каком-то этапе энтузиазм присутствовал и использование EAV планировалось для восьми типов сущностей, но по факту остановились на 4.


    'eav_entity_': пространство-призрак


    Пространство таблиц eav_entity напоминают китайские города-призраки — из 9 таблиц пространства данные содержатся только в двух:


    • eav_entity_type: это реестр типов сущностей, о которых я упоминал выше;
    • eav_entity_attribute: используется для упорядочивания атрибутов в группах (ближе к отображению данных, чем к их хранению); данная информация больше относится непосредственно к самим атрибутам, чем к сущностям (т.е., явно не из этого прихода — ей место в пространстве eav_attribute_ );

    Остальные 7 таблиц — пусты:


    • eav_entity
    • eav_entity_datetime
    • eav_entity_decimal
    • eav_entity_int
    • eav_entity_store
    • eav_entity_text
    • eav_entity_varchar

    Очень похоже на попытку унификации способа хранения значений для атрибутов сущностей в одном наборе таблиц (datetime, decimal, int, text, varchar) вместо того, чтобы иметь по 5 таблиц с соответствующими суффиксами для каждого типа сущностей. На неудачную попытку? Или это будущее EAV в Magento?


    image


    По-любому, Земля же была безвидна и пуста, и тьма над бездною, и Дух Божий в настоящем эти таблицы изначально не используются.


    Типы значений атрибутов


    В таблице eav_entity_type задаются типы сущностей, в таблице eav_attribute задаются сами атрибуты и их привязка к соответствующим типам сущностей. А как определить, где искать значение для такого-то атрибута такой-то сущности?


    В этом нам поможет поле eav_attribute.backend_type. Оно показывает, где сохраняются значения атрибутов:


    • static: в таблице с данными о самой сущности (например, значения для атрибута #9 — customer.email, нужно искать в таблице клиентов customer_entity в столбце email);

    Для остальных типов значения сохраняются в отдельных таблицах, в названиях которых префикс соответствует типу сущности (customer_, ...) а суффикс — одному из типов данных:


    • datetime
    • decimal
    • int
    • text
    • varchar

    Т.е., значения для атрибута #79 catalog_product.special_from_date типа datetime сохраняются в таблице catalog_product_entity_datetime. Значения для атрибута #77 catalog_product.price — в таблице catalog_product_entity_decimal.


    Что можно интересного увидеть в таблице eav_attribute в связи с типами значений? Как я уже отмечал выше, в данной таблице описаны атрибуты только для 4 типов сущностей из 8, зарегистрированных в eav_entity_type. При этом для сущностей типа customer и customer_address все атрибуты, определённые изначально, имеют тип значений static — т.е., являются обычными колонками в таблице и никак не используют преимуществ EAV-подхода. Таблицы:


    • customer_entity_datetime
    • customer_entity_decimal
    • customer_entity_int
    • customer_entity_text
    • customer_entity_varchar
    • customer_address_entity_datetime
    • customer_address_entity_decimal
    • customer_address_entity_int
    • customer_address_entity_text
    • customer_address_entity_varchar

    изначально пусты и могут быть использованы только программным путём (т.е., через админку, без сторонних расширений, нет возможности записать что-либо в эти таблицы).


    EAV для категорий


    Категории каталога — вот первая сущность, которая более-менее использует EAV подход в Magento. Тип сущности — catalog_category, всего изначальных атрибутов — 30, из которых не-статических — 26. То есть, значения только 4 атрибутов (children_count, level, path, position) сохраняются в таблице catalog_category_entity, остальные сохраняются в наборе таблиц catalog_category_entity_ [ datetime | decimal | int | text | varchar ].


    Структура таблиц из этого набора очень похожа как друг на друга, так и на аналогичные таблицы других типов сущностей (клиентов, их адресов и т.д.):


    CREATE TABLE `catalog_category_entity_datetime` (
      `value_id` int(11) NOT NULL AUTO_INCREMENT,
      `attribute_id` smallint(5) unsigned NOT NULL DEFAULT '0',
      `store_id` smallint(5) unsigned NOT NULL DEFAULT '0',
      `entity_id` int(10) unsigned NOT NULL DEFAULT '0',
      `value` datetime DEFAULT NULL,
      PRIMARY KEY (`value_id`),
      UNIQUE KEY `...` (`entity_id`,`attribute_id`,`store_id`),
      ...
    ) ...

    Для различных типов сохраняемых значений (datetime, decimal, int, text, varchar) меняется только тип колонки value. Данная структура позволяет сохранять отдельное значение (value) отдельного атрибута (attribute_id) отдельной сущности (entity_id) для отдельной витрины (store_id).


    В связи с архитектурными особенностями Magento добавляется дополнительная связь с витриной — store_id. Таким образом возможна локализация значений одного и того же атрибута одной и той же сущности для различных витрин. Категории каталога — это первые сущности в Magento, для которых можно использовать EAV-подсистему прямо "из коробки". Задавать значения для атрибутов каталогов можно через админку.


    image


    Можно не только давать различные значения для текстовых атрибутов, переводя на язык соответствующей витрины, но и локализовывать атрибуты других типов. Например, в преддверии рождественских праздников на ru-витринах магазина для атрибута catalog_category.custom_design_from можно выставить значения 7-го января следующего года, а на en-витринах — 24-го декабря этого.


    image


    EAV для продуктов


    В общем-то, это тот самый тип сущностей, ради которого EAV и затевалась в Magento. Тип сущности — catalog_product, всего изначальных атрибутов — 63, из которых не-статических — 56. Структура таблиц, поддерживающих EAV для продуктов, аналогична структуре таблиц для каталогов. Но есть одно значительное отличие. Для продуктов можно создавать новые атрибуты через админку — это default'овый функционал Magento, из коробки. Если для других сущностей Magento предоставляет только EAV структуры данных в расчёте на их программное заполнение, то для продуктов реализован интерфейс, позволяющий делать это на уровне пользователя (управляющего магазином) — Stores / Attributes / Product.


    Для продуктов задействованы ещё две таблицы, относящиеся к EAV:


    • eav_attribute_set
    • eav_attribute_group

    По-большому счёту, они скорее относятся к отображению информации, чем к её хранению. Атрибуты продукта объединяются в наборы (set) и при создании продукта ему присваивается набор атрибутов, что позволяет при заполнении карточки продукта для, например, телевизора, выбирать набор атрибутов, относящийся именно к бытовой технике (или даже для группы продуктов "телевизоры"). Объединение атрибутов в наборы происходит в Stores / Attributes / Product / Attribute Set:


    image


    Итого


    IMHO, Magento является хорошим примером того, что целесообразность применения EAV достаточно узкая. При закладке на использование EAV для 8 сущностей (eav_entity_type) EAV-нотация используется только для 4 сущностей (eav_attribute), из которых только 2 сущности имеют действительно EAV-атрибуты — catalog_category и catalog_product. Причём для catalog_category EAV-атрибуты используются не по своему прямому назначению (большое количество различных атрибутов для описания сущности при малом количестве атрибутов, относящихся к отдельному экземпляру), а для "по-витринной локализации" значений атрибутов (один и тот же набор атрибутов для сущности "категория каталога" с возможностью атрибута экземпляра иметь различные значения для различных витрин магазина).


    Полноценное использование EAV применяется только для catalog_product (правда и тут есть примесь "по-витринной локализации", но это уже расширение EAV-модели, а не её профанация, как в случае с категориями). Зато с продуктами Magento раскрывает EAV по полной — Magento-приложение можно смело использовать для наглядной демонстрации принципов EAV.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 4

      0
      Не понаятно зачем нужен тут eav_attribute_set когда есть catalog_category_entity? Разьве нельзя было использовать catalog_category_entity для группировки аттрибутов?
        0

        catalog_category_entity — это реестр категорий. В нём генерируются ID для отдельных экземпляров сущности типа "категория каталога". Обычно таблица-реестр содержит также и значения атрибутов сущностей в виде колонок в этой же таблице. Но ни о какой группировке на уровне структур данных в этом случае речь не идёт. Каждая строка (экземпляр сущности) содержит все колонки, которые есть в таблице.


        Теоретически, мы можем в catalog_category_entity добавить колонку attr_group, фиксировать там имя группы набора атрибутов и программно фильтровать, какие колонки (атрибуты) показывать для каких наборов (если я правильно понял вашу мысль), но в таблице всё равно каждая строка будет содержать null для неиспользуемых данным набором атрибутов колонок, и для неё будет зарезервировано место на диске.


        Другими словами в таблице на 500 колонок для каждой строки место на диске выделяется на все 500 колонок, даже если по факту в данной строке всегда будет использоваться всего 10 колонок.

          0
          к примеру есть категория одежда (таблица catalog_category_entity), есть продутк: платье (catalog_product_entity), категория этого продукта: одежда, есть атрибуты продукта: вид, цвет (eav_attribute), значения аттрибутов: узкий, красный (catalog_product_entity_text). Я правильно описал таблицы? Как я понимаю атрибуты завмисят от категорий товара, в моем примере категория товара ожеда, соответственно когдая я добавляю новый товар, аттрибуты должны сформироваться от выбранного категория.
          Не могли бы описать структуру базы данных товаров и категорий на примере?
            0

            Вы правильно понимаете и ваш подход имеет право на существование. Я просто описал EAV-структуру данных, которая реализована в Magento 2. Одна из многих.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое