> Как организовать таблицы и шардирование для хранения исторических данных (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: BrightPattern

Стек: Go

> Пример ответа

Для хранения исторических данных в Go-проекте оптимально использовать секционирование по времени (time‑based partitioning) и шардирование по ключу (например, user_id). Это позволяет эффективно управлять объёмом данных и обеспечивать быстрый доступ.

Структура таблиц:

  • Основная таблица events с полями: id (UUID), user_id (int64), event_type (varchar), created_at (timestamp), payload (jsonb).
  • Для исторических данных создаём секционированные таблицы по месяцам: events_2024_01, events_2024_02 и т.д. В PostgreSQL это делается через декларативное секционирование (PARTITION BY RANGE (created_at)).

Шардирование:

  • Используем consistent hashing для распределения данных по шардам (например, 8 шардов). Ключ шардирования - user_id, чтобы все события одного пользователя попадали в один шард.
  • В Go реализуем пул соединений к каждому шарду через database/sql и pgxpool. Пример:
GO
type ShardManager struct {
shards []*pgxpool.Pool
}
func (sm *ShardManager) getShard(userID int64) int {
return int(userID) % len(sm.shards)
}

Рекомендации:

  • Для запросов по диапазону дат используйте индексы на created_at и user_id.
  • Старые секции (старше N месяцев) можно отключать или переносить в холодное хранилище (S3, ClickHouse) через фоновые задачи.
  • В Go для фоновой архивации используйте time.Ticker и горутины с graceful shutdown.

Пример запроса к конкретной секции:

SQL
SELECT * FROM events WHERE created_at >= '2024-01-01' AND created_at < '2024-02-01';

Такой подход даёт линейную масштабируемость и упрощает обслуживание исторических данных.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью