Достался мне на переработку legacy проект в котором всё тормозит, еле-еле работает и вообще надо обновить кодовую базу. По факту оказалось, что дело не в коде - у проекта большая БД (2,5м+ записей в самой большой таблице, суммарно 11м+), жуткая структура и всё это на древнем мускуле который крутится на не свежих дисках. После обсуждения проблем Заказчик согласился обновить хотя бы диски и поставить их в raid, а бд решили заменить на Postgresql.
Мне дали время на тесты и я решил попробовать jsonb как замену EAV. Уточнение: я не администратор БД, я программист. Мои знания кончаются на написании несложных функций и вьюх.
Вот примерная струкура одной таблицы - карточка посетителя, таких таблиц 7:
tenant_id | id | name | fields | tags | ... еще 8 полей ...
-----------------------------------------------------------
1|1|"Название карточки"|[{"id":4,"name":"Сем.пол.","values":[{"value":"Холост","enum":123}]},{...}] | [{"id":3,"value":"Сургут"},{...}]
где:
fields::jsonb - Заполненные поля карточки, их безумное кол-во, часто обновляются, отношение к таблице FIELDS
tags::jsonb - Теги, отношение к таблице TAGS
Для каждого поля своя четкая структура хранения. В такие поля не входят вещи типа комментариев и т.п.
Из плюсов что я получил:
1. Размер БД почти 3 раза меньше чем со схемой EAV, jsonb 3750mb, EAV 11980mb
2. Данные находятся в одном месте, не нужно делать кучу джойнов.
Теперь проблемы и вопросы:
90% всех запросов - это выборка данных по ID, остальное это поиск и обновление.
Вопросы:
1. Если я храню данные в виде '[{...},{...}]' то:
а) Поиск типа data_json @> '[{"value":999}]' работает отлично, а как искать LIKE или есть какой нибудь нечеткий поиск? Если делать data_json::text like, то скорость поиска медленная, может есть какой-нибудь хитрый индекс для этого?
б) Как удалить элемент '{...}' массово в нескольких записях? Пока получается только по одной.
в) Если было обновлено название тега, как обновить массово во всех записях? Пока получается только по одной.
2. Если я храню данные в виде '{1:{...},22:{...}}' то:
Есть поиск по id элемента вроде data_json->'321'->>'values', и даже есть like по id элемента.
Вопрос: как искать строго по значению {value} либо LIKE'ать не зная id элемента?
3. В обоих случаях будут работать индексы на значения "второго" уровня? Т.е. для '[{"id":1, "values":[{"value":"Значение"}]},{...}]' ищем по "value".
В общем прошу совета, имеет ли смысл в этом разбираться сейчас и будет ли от jsonb реальный профит в поиске, или же делать на EAV? (структуру уже сделал и протестировал) Или может лучше прикрутить Эластик\Сфинкс?
Всем спасибо, решение найдено, стоило лучше искать.
Если кому-то будет интересно :
Для строгого поиска буду использовать ID элемента сущности, для остального взято решение с дополнением RUM отсюда http://komar.in/ru/mongodb-не-нужна