TGViewer
Happy Devops — сообщество адекватных инженеров Happy Devops — сообщество адекватных инженеров @happy_devops · 1.81K subscribers
Post #683 804
Переход на партиционированные таблицы в боевой системе похож на замену колес на едущей машине. Один неверный шаг — и вся система встанет. Разберем, как провести миграцию безопасно и что делать с гигантскими объемами данных.

Вот реальный кейс из практики. Таблица с данными о транзакциях весила 4 ТБ и росла на 50 ГБ в день. Запросы за последний месяц работали быстро благодаря индексам, но исторические отчеты могли считаться часами. Решение — партиционирование по месяцам.

Первый шаг — создание структуры:

CREATE TABLE transactions_new (
id bigint,
created_at timestamp,
amount decimal,
-- другие поля
) PARTITION BY RANGE (created_at);

-- Создаем партиции для каждого месяца
CREATE TABLE transactions_2024_01
PARTITION OF transactions_new
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');


Дальше начинается самое сложное — перенос данных. Прямой INSERT SELECT на таких объемах заблокирует таблицу на часы. Правильный путь — батчинг с параллельной обработкой:

-- Функция для переноса данных за один день
CREATE OR REPLACE FUNCTION migrate_day(day_start date)
RETURNS integer AS $$
BEGIN
RETURN WITH moved AS (
DELETE FROM transactions
WHERE created_at >= day_start
AND created_at < day_start + interval '1 day'
RETURNING *
)
INSERT INTO transactions_new
SELECT * FROM moved;
END;
$$ LANGUAGE plpgsql;

-- Запускаем параллельно для разных дней
SELECT migrate_day(day)
FROM generate_series('2023-01-01'::date, '2024-01-01', '1 day') day;


Во время миграции критично следить за нагрузкой на диски и CPU. Утилита pg_stat_progress_copy показывает прогресс операций. А автовакуум будет очищать старые версии строк, не давая таблице разрастаться.

Отдельная история — обслуживание партиций. Старые данные можно архивировать, перенося целые партиции на медленные диски:

-- Перемещаем старую партицию на другое табличное пространство
ALTER TABLE transactions_2023_01
SET TABLESPACE cold_storage;

-- Отключаем автовакуум для старых партиций
ALTER TABLE transactions_2023_01
SET (autovacuum_enabled = false);


Для автоматизации рутины помогает расширение pg_partman. Оно создает новые партиции заранее и может автоматически архивировать старые:

SELECT partman.create_parent(
'public.transactions',
'created_at',
'range',
'month',
p_premake := 3
);


И последнее: партиционирование требует изменений в приложении. Запросы без указания партиционного ключа будут сканировать все партиции. А значит, нужно научить ORM всегда добавлять created_at в условия поиска.

🏴‍☠️ @happy_devops
  • 👍 5
More from @happy_devops
  1. Nov 28, 2025⚡ Совместный карьерный митап от Звук и self, сообщества для поддержки айтишников. Как стро…
  2. May 29, 2025🔥 База знаний тимлида: как въехать в процессы быстро и безболезненно! Подкаст Виктор Коре…
  3. Apr 16, 2025Дорогие друзья, уже на следующей неделе, 23 апреля в Амфитеатре Санкт-Петербургского конгр…
  4. Mar 28, 2025Eventual Consistency: когда доступность важнее мгновенной согласованности Eventual consist…
  5. Mar 26, 2025Гонка за новым функционалом не должна превращать систему в «хрупкого гиганта». SRE-практик…
  6. Mar 19, 2025Strong Consistency: между производительностью и надежностью данных Strong consistency — кл…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →