Ответ
В последнем проекте на PostgreSQL общий объем данных составлял около 500 ГБ. Основные таблицы:
| Таблица | Примерный объем записей | Назначение |
|---|---|---|
users |
~10 млн | Данные пользователей |
transactions |
~150 млн | Финансовые операции |
action_logs |
~1 млрд | Логирование действий |
Примененные методы оптимизации:
- Индексация: Создание составных индексов для частых запросов.
@Entity @Table(name = "transactions", indexes = { @Index(name = "idx_user_created", columnList = "user_id, created_at") }) public class Transaction { ... } - Партиционирование: Таблица
action_logsбыла разделена по диапазонам дат (PARTITION BY RANGE (created_at)). - Репликация: Настройка реплик для чтения, чтобы разгрузить primary-сервер.
Нагрузка составляла до 5k RPS, средний размер строки — 1-2 КБ.
Ответ 18+ 🔞
Да ты послушай, что у нас тут за цирк с конями развернулся! Последний проект на PostgreSQL, блядь, — это просто песня. Общий объём данных — около 500 гигов, нехило так, да? А внутри — три кита, на которых всё держится, и держится, надо сказать, с переменным успехом.
Вот смотри, какие у нас главные герои в этой эпопее:
| Таблица | Записей, блядь (примерно) | Чем занимается |
|---|---|---|
users |
~10 лямов | Тут наши пользователи, народ, так сказать. |
transactions |
~150 лямов | Финансовые операции, бабло туда-сюда. |
action_logs |
~1 миллиард, Карл! | Логирование действий, куча всякого мусора, который «на всякий случай». |
И знаешь, что самое весёлое? Эта таблица action_logs — она же просто пиздец! Миллиард записей, ёпта! Представляешь? Это ж надо было столько наляпать. Ну, мы, конечно, не лыком шиты, пришлось эту махину как-то укрощать.
Что мы с этим добром делали, чтобы не сдохнуть:
-
Индексация, мать её. Без неё — просто пипец, всё встанет колом. Для самых частых запросов лепили составные индексы. Вот, смотри, как в коде это выглядело, красота же:
@Entity @Table(name = "transactions", indexes = { @Index(name = "idx_user_created", columnList = "user_id, created_at") }) public class Transaction { ... }Чтобы когда ищут транзакции по юзеру и дате — не перерывали всю таблицу, как свиньи корыто.
-
Партиционирование. Это вообще спасение для нашей
action_logs. Мы её, бедную, порезали на куски по датам (PARTITION BY RANGE (created_at)). Теперь когда нужно старые логи вычистить или запрос за вчера сделать — не надо ковыряться во всём миллиарде, только в одном куске. Гениально и просто, как тапок. -
Репликация. Ну, куда ж без неё. Настроили реплики для чтения, чтобы primary-сервер не ебался со всеми этими «просто посмотреть» запросами. Пусть рабы работают, а царь-сервер пусть важные дела делает — пишет данные.
А нагрузка, представляешь, до 5 тысяч запросов в секунду доходила! RPS, блядь! И каждая строка в среднем по 1-2 килобайта. В общем, не скучали. Иногда казалось, что сейчас всё накроется медным тазом, но нет, вывезли. Хуй с горы, но вывезли.