Много параметров у модели: сериализация или отдельная таблица?

Возник у меня вопрос следующего характера.

В данный момент, я проектирую некое веб-приложение на PHP/Yii. В нём есть некая структура моделей, связанных с базой данных MySQL при помощи Active Record.
Для каждой модели я уже прописал поля в базе данных, которые ей точно нужны и по которым нужно будет искать записи. Однако у каждой модели в будущем будет много других параметров, о которых я пока не знаю. Более того, в процессе развития из будет становиться всё больше.
Поэтому я хочу расширить Active Record так, чтобы я мог складывать в базу произвольные параметры, даже если для этого параметра нет поля в базе данных.
И я вижу два решения для этого:
1. Складывать все эти параметры в массив, который будет сериализовываться/десериализовываться при записи/получении из базы и храниться в отдельном поле.
2. Складывать эти параметры в отдельную таблицу в базе данных, с полями типа id, model_name, model_id, param_name, value.

Какие у этих способов есть преимущества и недостатки, и какой из них "правильнее"?
  • Вопрос задан
  • 4084 просмотра
Решения вопроса 3
papahoolio
@papahoolio
Похоже, что при описании проблемы упущен важный момент, а как эти поля будут использоваться. Нужны ли будут данные из них всегда или только в определенных случаях?

Давай посмотрим плюсы и минусы решений. Ну как я их вижу.
Для варианта номер один.
Плюсы:
- со стороны PHP легко будет расширить AR
Минусы:
- unserialize медлено, есть конечно json и igbinary, но это все равно время
- если полей "будет становиться всё больше", то в MySQL сериализованые данные нужно будет хранить в TEXT/BINARY поле, если мы говорим о стандартных ENGINE MySQL, то при выборке такие поля в память не загружаются, а читаются с диска, ну ты понимаешь, что дисковые I/O операции дорогие (в случае с InnoDB там может быть лучше ситуация)
- если у нас случай, когда данные из "неизвестных" полей нам нужны редко, то при таком подходе, либо надо будет рисовать workaround в AR чтобы эти поля не тащить, либо будут данные постоянно пересылаться м/у БД и PHP, плюс в памяти PHP висеть
- если база разрастется и нужно будет вытащить "неизвестное" поле в поиск/фильтрацию, изменение схемы таблицы потребует времени, вытаскивание данных из сериализованного поля и заполнение нового поля - потребует времени, построение индекса по новому полю - потребует времени. Много данных - много времени, времени простоя сервиса.

Для варианта два.
Плюсы:
- если размер данных в полях лимитирован и залезает в тип VARCHAR, решаем проблему номер два первого способа
- масштабируемо
- внедрение поиска/фильтра по полю не повлечет переделывания структуры таблиц
Минусы:
- если данные нужны всегда, получится JOIN,если полей с данными будет много, то JOIN будет медленным. Если тип у полей будет TEXT... ну ты понял :)
- проблему один можно решить кешированием, но реализация на PHP в рамках AR уже станет не самой простой задачей
- да вообще в рамках AR Yii реализация такого подхода с lazy loading потребует нормального такого понимания, как AR в Yii устроен и где его надо менять, чтобы всем было хорошо

Правильного варианта, как ты понимаешь нет, нужно взвесить все "за" и "против", понять насколько имеет смысл делать "круто" сейчас и тратить время или можно залезть в technical debt, но быстро запуститься уже завтра.
Ответ написан
@Nc_Soft
Если это просто справочные поля, то сериализация подойдет, если по ним надо будет делать выборки , то нет.
Ответ написан
jbmeerkat
@jbmeerkat
Ruby / Ruby on Rails developer
если используется postgres, то можно сериализовать в JSON, делать по нему выборки и строить индексы. например тут можно почитать clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/
надо смотреть насколько это критично по производительности, естественно, что работа с JSON будет медленнее
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Чем не устраивает связь многих ко многим?
когда есть одна таблица это некоторая сущность, вторая содержит некоторые параметры, а третья, связывающая, содержит FK на первые две (можно чтобы в третьей и значения хранились, так думаю даже лучше)
Ответ написан
TTA
@TTA
Мутировавший технарь :)
Делал EAV (многие ко многим) на начальном этапе в проекте одном. Потом отказался. Т.к. количество гемора только больше. Все равно если хотите нативную валидацию надо заводить в модели переменную, настраивать геттер и сеттер, обрабатывать beforeSave и т.п. Я к тому ж еще использовал стороннюю компоненту EAV, там она еще просила метаданных. В итоге плюнул, сделал поля в таблице и не парюсь.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы