Архивирование старых данных БД: стратегия и реализация

Таблица `events` с 500 миллионами строк и ростом 2 миллиона в сутки — это проблема, которая становится острее каждый день. `SELECT` тормозит, `VACUUM` не успевает, индексы занимают гигабайты. Без архивирования база распухает, блокировки мешают работе, а стоимость хранения на SSD бьёт по бюджету. Мы

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Архивирование старых данных БД: стратегия и реализация
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1419
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    983
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1244
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    998

Таблица events с 500 миллионами строк и ростом 2 миллиона в сутки — это проблема, которая становится острее каждый день. SELECT тормозит, VACUUM не успевает, индексы занимают гигабайты. Без архивирования база распухает, блокировки мешают работе, а стоимость хранения на SSD бьёт по бюджету. Мы решаем такие задачи под ключ — реализуем систему архивирования, которая отделяет горячие данные от холодных без простоев и потери производительности. Наш опыт показывает, что правильная стратегия архивирования снижает нагрузку на базу данных на 70% и сокращает стоимость хранения в 2–3 раза.

Какие проблемы решает архивирование старых данных?

Основная боль — деградация производительности. Когда таблица разрастается, даже простые SELECT с индексом тормозят из-за глубины B-tree и фрагментации. VACUUM не успевает чистить мёртвые строки, и autovacuum отстаёт. Рост затрат на хранение — дорогое SSD-хранилище для данных, к которым обращаются раз в год. Блокировки при массовом удалении — DELETE без батчей блокирует таблицу на минуты. Мы решаем это через батчевое архивирование с SKIP LOCKED — параллельные воркеры не конфликтуют.

После архивирования нагрузка на диск снижается на 70%, время SELECT уменьшается в 3–5 раз, а размер базы сокращается в 2 раза.

Стратегии архивирования: сравнение методов

Partition detach — если таблица партиционирована, старые партиции отсоединяются и переносятся в архивную базу или tablespace. Это самый быстрый подход: операция метаданных, без перемещения строк. Partition detach быстрее батчевого INSERT+DELETE в 50 раз для таблиц с миллиардами строк.

INSERT + DELETE батчами — для непартиционированных таблиц. Копируем строки в архивную таблицу батчами, удаляем из основной. Не создаёт длинных транзакций и позволяет контролировать нагрузку.

Логическая реплика — настраиваем publication на основной базе, subscription на архивной, с фильтром по дате. Архив обновляется в реальном времени — подходит для аудита.

Dump + truncate — экспорт в CSV/parquet, удаление из базы. Данные больше не в PostgreSQL/MySQL — только в файловом архиве. Самый дешёвый вариант хранения.

Как выбрать подходящий метод?

Метод Скорость Нагрузка на БД Сложность
Partition detach Высокая Минимальная Средняя
INSERT+DELETE батчами Средняя Умеренная Низкая
Логическая реплика Низкая Минимальная Высокая
Dump+truncate Высокая Высокая Низкая

Как мы реализуем архивирование: пошаговая инструкция

Шаг 1: Анализ структуры и нагрузки

Оцениваем объём, скорость роста, частоту запросов к старым данным. Определяем, какие таблицы можно партиционировать.

Шаг 2: Выбор стратегии

По таблице выше определяем оптимальный метод. Для большинства проектов подходит батчевое копирование с SKIP LOCKED.

Шаг 3: Написание функции с SKIP LOCKED

Используем батчи по 10 000 строк с паузой 0.1 с. Функция archive_old_events переносит строки из public.events в archive.events:

-- Архивная таблица (может быть в отдельной схеме или базе) CREATE TABLE archive.events ( LIKE public.events INCLUDING ALL ); -- Функция архивирования с батчами CREATE OR REPLACE FUNCTION archive_old_events( p_before_date TIMESTAMPTZ, p_batch_size INTEGER DEFAULT 10000 ) RETURNS TABLE(batches_processed INTEGER, rows_archived BIGINT) LANGUAGE plpgsql AS $$ DECLARE v_batches INTEGER := 0; v_total BIGINT := 0; v_moved INTEGER; BEGIN LOOP -- Переносим один батч в архив WITH moved AS ( DELETE FROM public.events WHERE id IN ( SELECT id FROM public.events WHERE created_at < p_before_date LIMIT p_batch_size FOR UPDATE SKIP LOCKED -- пропускаем заблокированные строки ) RETURNING * ) INSERT INTO archive.events SELECT * FROM moved; GET DIAGNOSTICS v_moved = ROW_COUNT; EXIT WHEN v_moved = 0; v_batches := v_batches + 1; v_total := v_total + v_moved; -- Пауза между батчами — не перегружаем диск PERFORM pg_sleep(0.1); -- Прогресс RAISE NOTICE 'Batch %: % rows archived (total: %)', v_batches, v_moved, v_total; END LOOP; RETURN QUERY SELECT v_batches, v_total; END $$; 

Запуск:

SELECT * FROM archive_old_events('давняя_дата'::timestamptz, 10000); 

Шаг 4: Настройка планировщика

Artisan-команда запускается ежемесячно в 2:00:

// app/Console/Commands/ArchiveOldData.php class ArchiveOldData extends Command { protected $signature = 'db:archive {--days=365 : Архивировать данные старше N дней}'; protected $description = 'Archive old records to archive tables'; public function handle(): int { $beforeDate = now()->subDays($this->option('days'))->toDateTimeString(); $this->info("Archiving events before {$beforeDate}..."); $result = DB::selectOne( 'SELECT * FROM archive_old_events(?::timestamptz, 5000)', [$beforeDate] ); $this->info("Done: {$result->batches_processed} batches, {$result->rows_archived} rows"); // VACUUM после массового удаления DB::statement('VACUUM ANALYZE events'); return self::SUCCESS; } } 
// app/Console/Kernel.php $schedule->command('db:archive --days=180') ->monthlyOn(1, '02:00') ->withoutOverlapping() ->onFailure(fn() => Notification::route('telegram', config('services.telegram.ops_chat')) ->notify(new ArchivingFailedNotification())); 

Шаг 5: Мониторинг и VACUUM

После архивации выполняем VACUUM ANALYZE. Настраиваем алерты на ошибки через Telegram.

Шаг 6: Восстановление из архива

Из архивной таблицы — ATTACH PARTITION к основной без копирования. Из CSV-файлов — COPY-загрузка.

Как восстановить данные из архива?

Из архивной таблицы — ATTACH PARTITION к основной таблице без копирования данных. Из CSV-файлов — COPY-загрузка:

# Восстановить данные из CSV-архива обратно в базу gunzip -c /mnt/archive/events/2024-01/events_2024-01.csv.gz | \ psql -d mydb -c "COPY events FROM STDIN CSV HEADER" 

Для долгосрочного хранения используем файловый архив с ротацией.

Что входит в работу

  • Анализ структуры таблиц и нагрузки
  • Проектирование схемы архива (партиционирование, отдельная БД или файлы)
  • Написание функций/скриптов архивации
  • Настройка планировщика и мониторинга
  • Политика хранения с ротацией
  • Сценарий восстановления из архива
  • Документация процесса и обучение команды

Сроки реализации

Этап Срок
Анализ и проектирование 0.5 дня
Реализация функции архивации 1–1.5 дня
Настройка планировщика и мониторинга 0.5 дня
Документация и обучение 0.5 дня
Общий срок 2.5–3.5 дня

Типичные ошибки

  • Забыть про VACUUM после массового удаления — таблица раздувается.
  • Использовать одну транзакцию для всего объёма — рискуем откатом на часы.
  • Не проверять архив перед удалением — потеря данных.
  • Игнорировать SKIP LOCKED — параллельные процессы блокируют друг друга.

Почему стоит доверить архивирование нам

У нас более 10 лет опыта в администрировании PostgreSQL и MySQL. Мы реализовали системы архивирования для проектов с петабайтами данных. Гарантируем, что процесс не затронет основную бизнес-логику и будет полностью автоматизирован. Свяжитесь с нами — мы оценим ваш проект и предложим оптимальное решение. Получите консультацию инженера по производительности БД — бесплатно.

Для получения дополнительной информации обратитесь к официальной документации PostgreSQL. Политика хранения согласовывается с требованиями бизнеса и регулятора (например, GDPR).