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

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

В данный момент, я проектирую некое веб-приложение на PHP/Yii. В нём есть некая структура моделей, связанных с базой данных MySQL при помощи Active Record.  

Для каждой модели я уже прописал поля в базе данных, которые ей точно нужны и по которым нужно будет искать записи. Однако у каждой модели в будущем будет много других параметров, о которых я пока не знаю. Более того, в процессе развития из будет становиться всё больше.  

Поэтому я хочу расширить Active Record так, чтобы я мог складывать в базу произвольные параметры, даже если для этого параметра нет поля в базе данных.  

И я вижу два решения для этого:  

1. Складывать все эти параметры в массив, который будет сериализовываться/десериализовываться при записи/получении из базы и храниться в отдельном поле.  

2. Складывать эти параметры в отдельную таблицу в базе данных, с полями типа id, model\_name, model\_id, param\_name, value.  
  

Какие у этих способов есть преимущества и недостатки, и какой из них "правильнее"? 

 Похоже, что при описании проблемы упущен важный момент, а как эти поля будут использоваться. Нужны ли будут данные из них всегда или только в определенных случаях?  
  

Давай посмотрим плюсы и минусы решений. Ну как я их вижу.  

Для варианта номер один.  

Плюсы:  

 - со стороны 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, но быстро запуститься уже завтра. 

 Если это просто справочные поля, то сериализация подойдет, если по ним надо будет делать выборки , то нет. 

 если используется postgres, то можно сериализовать в JSON, делать по нему выборки и строить индексы. например тут можно почитать [clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/](http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/)  

надо смотреть насколько это критично по производительности, естественно, что работа с JSON будет медленнее 

 Чем не устраивает связь многих ко многим?  

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

 Делал EAV (многие ко многим) на начальном этапе в проекте одном. Потом отказался. Т.к. количество гемора только больше. Все равно если хотите нативную валидацию надо заводить в модели переменную, настраивать геттер и сеттер, обрабатывать beforeSave и т.п. Я к тому ж еще использовал стороннюю компоненту EAV, там она еще просила метаданных. В итоге плюнул, сделал поля в таблице и не парюсь.