Что такое EAV простыми словами
EAV (Entity-Attribute-Value) — это способ хранения данных, при котором вместо фиксированных колонок в таблице у тебя есть три сущности:
- Entity — объект (например, товар)
- Attribute — характеристика (цвет, размер, вес)
- Value — значение этой характеристики
Вместо нормальной таблицы вида:
products
id | name | color | size
получаешь что-то вроде:
entity_id | attribute | value
1 | color | red
1 | size | L
То есть структура данных становится не жесткой, а динамической.
—
Зачем вообще нужен EAV
Основная причина — гибкость.
Когда у тебя:
- динамический набор полей
- разные сущности с разной структурой
- часто меняющиеся требования
EAV позволяет не трогать схему базы каждый раз, когда бизнес придумал новое поле.
Типичный кейс — каталог товаров:
- у телефона есть «диагональ экрана»
- у обуви — «размер»
- у холодильника — «объем»
Сделать одну нормальную таблицу под это — боль. EAV решает это элегантно. На бумаге 🙂
—
Как это обычно реализуют
Классическая схема:
Таблица сущностей
entities
id | name
Таблица атрибутов
attributes
id | name
Таблица значений
values
entity_id | attribute_id | value
Иногда добавляют типы значений (int, string, json), но суть та же.
—
Плюсы EAV
Почему его вообще используют:
- Гибкость — можно добавлять атрибуты без миграций
- Универсальность — подходит под разные типы сущностей
- Расширяемость — удобно для кастомных полей
Если делаешь админку с пользовательскими полями — EAV прям просится.
—
Минусы (и вот тут начинается боль)
Теперь реальность.
1. Сложные запросы
Любая выборка превращается в JOIN-ад:
SELECT e.*
FROM entities e
JOIN values v1 ON v1.entity_id = e.id AND v1.attribute_id = 1
JOIN values v2 ON v2.entity_id = e.id AND v2.attribute_id = 2
И чем больше фильтров — тем веселее.
—
2. Производительность
EAV плохо масштабируется:
- много JOIN’ов
- сложно индексировать
- плохо работает с агрегациями
На маленьких данных — ок. На больших — начинаются страдания.
—
3. Потеря типизации
Значения часто хранятся как строки:
value = "100"
И ты потом:
- парсишь типы
- ловишь баги
- плачешь
—
4. Усложнение кода
ORM-магия заканчивается:
- кастомные репозитории
- ручная агрегация
- костыли в бизнес-логике
Laravel тут не спасает — EAV всё равно нужно обрабатывать руками.
—
Когда EAV — это норм
Использовать можно, если:
- данные реально динамические
- структура часто меняется
- нет жестких требований к производительности
- это админка / CMS / конструктор
Классические кейсы:
- каталоги товаров
- кастомные поля пользователей
- форм-билдеры
—
Когда EAV — плохая идея
Не стоит использовать, если:
- структура данных известна заранее
- важна производительность
- нужны сложные аналитические запросы
Если ты просто ленишься делать миграции — EAV не решение 🙂
—
Альтернативы EAV
Часто лучше посмотреть в сторону:
1. JSON-колонки
attributes JSON
Плюсы:
- проще
- быстрее
- поддержка индексов (в PostgreSQL/MySQL)
—
2. Отдельные таблицы под типы
Иногда лучше сделать:
- products_phones
- products_shoes
Да, больше кода — но меньше боли потом.
—
3. Полиморфные связи
В Laravel можно аккуратно обойтись без EAV через morph-отношения.
—
Вывод
EAV — это не серебряная пуля. Это инструмент.
Он отлично работает в нишевых задачах, но превращается в кошмар, если использовать его везде подряд.
Главное правило:
Если можешь обойтись без EAV — обходись.
Если не можешь — используй осознанно и готовься платить за это сложностью.