Кто-нибудь реализовал очень большую базу данных EAV или открытой схемы в SQL Server? Мне интересно, есть ли здесь проблемы с производительностью и как вы смогли преодолеть эти препятствия.





Я не эксперт по EAV, но несколько более опытных разработчиков, чем я, прокомментировали, что среда электронной коммерции Magento с открытым исходным кодом работает медленно, в первую очередь из-за архитектуры EAV через MySQL. Самый очевидный недостаток преодолеть нелегко. В этом заключается сложность устранения неполадок, где и как представлена информация для сущностей и значений атрибутов по мере увеличения размера приложения. Второй аргумент против EAV, который я слышал, заключается в том, что для него требуются соединения таблиц, которые превращаются в низкие двузначные цифры, но было отмечено, что использование InnoDB вместо MyISAM улучшило производительность (или это могло быть наоборот, но я не могу полностью вспомнить ).
Независимо от MS SQL Server и любой другой марки базы данных, наихудшая проблема производительности с EAV заключается в том, что люди пытаются выполнять гигантские запросы для восстановления объекта в одной строке. Для этого требуется отдельное соединение для каждого атрибута.
SELECT e.id, a1.attr_value as "cost", a2.attr_value as "color",
a3.attr_value as "size", . . .
FROM entity e
LEFT OUTER JOIN attrib a1 ON (e.entity_id = a1.entity_id AND a1.attr_name = 'cost')
LEFT OUTER JOIN attrib a2 ON (e.entity_id = a2.entity_id AND a2.attr_name = 'color')
LEFT OUTER JOIN attrib a2 ON (e.entity_id = a3.entity_id AND a3.attr_name = 'size')
. . . additional joins for each attribute . . .
Независимо от того, какой бренд базы данных вы используете, большее количество объединений в запросе означает геометрическое увеличение затрат на производительность. Неизбежно, вам понадобится достаточно атрибутов, чтобы превзойти архитектурные возможности любого механизма SQL.
Решение состоит в том, чтобы получить атрибуты в строках, а не в столбцах, и написать класс в коде приложения, чтобы перебирать эти строки, присваивая значения свойствам объекта одно за другим.
SELECT e.id, a.attr_name, a.attr_value
FROM entity e JOIN attrib a USING (entity_id)
ORDER BY e.id;
Этот SQL-запрос настолько проще и эффективнее, что компенсирует лишний код приложения.
В структуре EAV я бы искал некоторый шаблонный код, который извлекает многострочный результирующий набор, подобный этому, и сопоставляет атрибуты со свойствами объекта, а затем возвращает коллекцию заполненных объектов.