Материалы / Истории / Партиции — не панацея
История

Партиции — не панацея

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

— …и поэтому я предлагаю партицировать таблицу заявок на кредит, — уверенно завершил Илья. — Она уже весит под сотню гигабайт, запросы тормозят.

В переговорке повисла одобрительная тишина. Идея прозвучала как спасение. Макс медленно поднял глаза.

— Илья, хорошая инициатива. Давай проясним. По какому ключу мы будем делить таблицу?

— Ну, по дате подачи заявки, конечно. По полю created_at, помесячно. Это же логи, по сути.

— Логично, — кивнул Макс. — А теперь скажи, какой самый важный и самый “больной” для нас запрос к этой таблице? Ради чего мы вообще храним всю эту историю?

— Ну… для отчетности, — начал Илья. — Сколько заявок было в прошлом квартале…

— Допустим, — прервал его Макс. — А еще? Для чего нашему банку нужна история заявок за 5 лет?

Илья задумался. В обсуждение включилась Таня:

— Для скоринга. Когда приходит новая заявка, мы должны оценить историю клиента. Мы смотрим, как часто он подавал заявки раньше, были ли отказы…

— Именно! — Макс подался вперед, и его голос обрел стальную твердость. — Мы ищем все заявки по passport_number или client_id за все время. Чтобы построить полную кредитную историю. А теперь вопрос, как партицирование по дате поможет нам ускорить этот поиск?

Взгляд Ильи дрогнул. Стало очевидно, что никак.

— Ребята, я понимаю, откуда это идет. Мы слышим “большая таблица — партицируй” и думаем, что это аксиома. Но партицирование — это не волшебная палочка. Это сложный, мощный и опасный инструмент. Точно как скальпель хирурга.

Он обвел взглядом команду.

— Вы видите только плюсы: легкое удаление старых данных, быстрые отчеты по датам. Но есть и обратная сторона, и она может ударить очень больно.

Первая и главная проблема — важный запрос не получает отсечения партиций. Чтобы оценить кредитную историю, придётся заглянуть в каждую месячную партицию за все годы. Вместо одного индексного поиска по passport_number получится 60 небольших сканов и Append. Это не обязательно катастрофа, но накладные расходы растут вместе с числом партиций, а ускорения от деления по дате такой запрос не получает. Решение нужно проверить на реальных данных и параллельной нагрузке.

Вторая проблема — ограничения. Мы хотим, чтобы app_id был глобально уникальным, верно? Для UNIQUE или PRIMARY KEY на декларативно партиционированной таблице PostgreSQL требует включить все столбцы ключа партиционирования. Если делить по created_at, обычное ограничение только на app_id создать не получится. Значит, глобальную уникальность придётся обеспечивать другой моделью данных, отдельным реестром или возможностями выбранной СУБД — и отдельно анализировать конкурентность такого решения.

Третья — сложность. Это не “сделал и забыл”. Придется писать и поддерживать скрипты для создания новых партиций. Партицирование это дополнительные накладные расходы на администрирование.

Макс откинулся на спинку стула.

— Поэтому, прежде чем мы произнесем слово “партицирование”, мы должны, как врачи перед операцией, пройтись по чек-листу:

  • Какую проблему мы решаем? Если это медленное регулярное удаление старых записей (DELETE) — да, это наш кандидат. Но действительно ли мы их удаляем, или они нужны нам для истории?

  • По какому полю фильтруют наши самые частые и критичные для бизнеса запросы? Если это отчеты по датам — хорошо. А если это скоринг по client_id за все время — СТОП. Мы рискуем все испортить.

  • Каков жизненный цикл наших данных? Да, это временной ряд. Но все ли данные со временем становятся “холодными”? Или заявка пятилетней давности так же важна для оценки кредитной истории, как и вчерашняя?

  • Нужна ли нам глобальная уникальность по полю, не входящему в ключ партицирования? Да, app_id должен быть уникален. И это уже техническое препятствие.

Он сделал глоток воды.

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

Макс закончил. Слайд на стене больше не выглядел как проблема, требующая немедленного решения. Он выглядел как задача, требующая глубокого и вдумчивого анализа.