Как сохранять в БД данные о больших объектах (где-то 120-200 полей)?
Приветствую!
На поточном проекте появилась задача сохранять в БД данные о больших объектах (где-то 120-200 полей). Эти данные практически никогда не будут запрашиваться одновременно. Скорее всего они будут запрашиваться порциями по 20-40 полей. Также, известно, что выборки будут редко пересекаться, чаще всего выборки будут идти сегментами, например от 1-го до 20-го поля, от 21-го до 40-го и т.д, но все же могут возникать ситуации когда выборки будут пересекаться.
Вопрос:
Как лучше представить такой объект в схеме БД?
Я не db-архитектор, посему могу ошибаться, но мне видятся 2 возможных варианта:
1. Создать несколько таблиц согласно предполагаемым сегментам. Предположительные плюсы: лучший кэш, возможность легкого шардинга по сравнению с партицированием монолитной таблицы. Минусы: overhead на ключевые поля и join'ы, overhead на разруливание на уровне логики приложения, не очень интуитивная схема и не очень легкий контроль данных.
2. Создать одну большую таблицу. Плюсы: предположительно лучший кеш, отсутствие overhead'а на join'ы и ключеые поля. Минусы — предположительные проблемы при масштабировании.
Ответ вроде бы очевиден, но я хочу просить совета именно с точки зрения производительности и опыта старших) Система большая и сложная, и мы можем позволить себе чуть сложнее написать код, но добиться лучшей производительности. Даже прирост в 5% будет ценным. Тесты пока не делал. Решил сначала спросить.
Данные поля участвуют в запросах или в условиях выборки? Или их надо только хранить, а запрашиваются по 2-3 (пусть 10) ключевым полям?
Запросы идут только за последний час/день или за все время?
Сколько порций данных ожидается в течении дня (и будет ли расти это число)?
@SabMakc, поля участвуют в запросах. Условия выборки заведомо известны на уровне логики. Сейчас трудно сказать сколько полей будет запрашиваться, но точно не все. Предполагаю, что основная часть выборки будет по 20-30 полей/запрос. Данные будут запрашиваться постоянно на протяжении приблизительно 16 часов/сутку. Мы ожидаем ~5к-6к запросов/сек.
Стоит также сказать, что записей в таблицах будет не так много - около 60к-100к на пиковых нагрузках. Именно поэтому хочется максимально задействовать кэш. Памяти у нас не очень много, да и посчитать сколько ее потребуется на данном этапе сложно (много text-полей).
Просто я хотел предложить часть данных сохранить в виде сериализованных объектов. Но этой подойдет только в том случае, если эти данные не участвуют в условиях выборки, а только запрашиваются. Или несколько полей-объектов - для каждой группы свой. Такой метод хранения подойдет как для одной, так и для нескольких таблиц.
Всё, конечно, зависит от деталей. Тут может быть столько деталей, что даже наводящие вопросы смысла нет задавать. Но.
Лучше делать отдельные таблицы. Это один из принципов управления сложностью. Называется декомпозиция. Если появляются такие страшные цифры в 100-120 полей таблицы, то значит, что с таблицей что-то не так.
Спасибо. Я знаю о декомпозиции и даже использовал это слово в заголовке, но НЛО переименовало вопрос ;) А если серьёзно, то да, мы, конечно же думаем над этим, но проблема то как раз в том, что данные эти уж слишком связаны друг с другом и в неплохом таком проценте случаев нужно будет запрашивать данные из 2з-3х таблиц. Просто хочется оптимально.
Поля, по которым нужно что-то интенсивно делать, надо иметь отдельно, а остальные - в hstore. hstore мы придумали как раз для таких задач, когда есть очень много "хлама", который нужен только для показа. Правда, потом, мы добавили индексы и теперь в этом хламе можно еще и искать :)