← Назад к статьям

Оптимизация базы данных Jira: очистка и обслуживание

База данных — это сердце Jira. Со временем она разрастается, появляются "мёртвые" данные, индексы фрагментируются, производительность падает. Я видел инстансы, где размер БД вырос в 10 раз за 3 года, а производительность упала в 5 раз. Регулярное обслуживание базы данных критично для поддержания производительности. В этой статье разберу практические техники очистки и оптимизации.

Почему база данных деградирует

Со временем в базе данных Jira накапливаются проблемы:

  • Удалённые объекты — Jira не удаляет данные физически, а помечает как удалённые
  • Фрагментация индексов — после множества операций INSERT/UPDATE индексы становятся неоптимальными
  • Устаревшие данные — старые логи, временные данные, кэши
  • Растущие таблицы — некоторые таблицы растут быстрее других и требуют внимания
  • Отсутствие статистики — оптимизатор запросов использует устаревшую статистику

Все эти факторы в совокупности приводят к замедлению работы системы. Регулярное обслуживание помогает поддерживать производительность на приемлемом уровне.

Анализ состояния базы данных

Перед началом оптимизации нужно понять текущее состояние базы данных. Разные СУБД имеют разные инструменты для анализа.

Размер таблиц

Первое, что нужно проверить — какие таблицы занимают больше всего места. Для PostgreSQL:

SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 20;

Для MySQL:

SELECT 
    table_name,
    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)"
FROM information_schema.TABLES
WHERE table_schema = 'jira'
ORDER BY (data_length + index_length) DESC
LIMIT 20;

Обычно самые большие таблицы — это jiraissue, changegroup, changeitem, jiraaction (комментарии), fileattachment.

Фрагментация индексов

Фрагментация индексов — это когда индекс разбит на множество мелких блоков вместо нескольких больших. Это замедляет чтение. Для PostgreSQL можно проверить фрагментацию:

SELECT 
    schemaname,
    tablename,
    indexname,
    pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_stat_user_indexes
WHERE schemaname = 'public'
ORDER BY pg_relation_size(indexrelid) DESC;

Статистика использования таблиц

Важно понимать, какие таблицы используются часто, а какие редко. Это помогает приоритизировать оптимизацию. Для PostgreSQL:

SELECT 
    schemaname,
    tablename,
    seq_scan,
    seq_tup_read,
    idx_scan,
    idx_tup_fetch,
    n_tup_ins,
    n_tup_upd,
    n_tup_del
FROM pg_stat_user_tables
WHERE schemaname = 'public'
ORDER BY seq_scan + idx_scan DESC;

Очистка удалённых объектов

Когда пользователь удаляет задачу, комментарий или другой объект в Jira, он не удаляется физически из базы данных. Вместо этого устанавливается флаг "deleted". Это позволяет восстановить данные, но со временем накапливаются "мёртвые" записи.

Анализ удалённых объектов

Сначала нужно понять, сколько удалённых объектов накопилось. Для задач (таблица jiraissue):

SELECT COUNT(*) 
FROM jiraissue 
WHERE resolution = (SELECT id FROM resolution WHERE pname = 'Deleted');

Для комментариев (таблица jiraaction):

SELECT COUNT(*) 
FROM jiraaction 
WHERE actiontype = 'delete' OR actionbody IS NULL;

Удаление старых удалённых объектов

Jira имеет встроенную функцию для удаления старых удалённых объектов, но она не всегда очевидна. Можно использовать API или прямой SQL (осторожно!).

Внимание: удаление данных необратимо. Обязательно создайте бэкап перед очисткой.

Через Jira API можно использовать функцию экспорта/импорта для очистки, но это сложно для больших объёмов данных. Для production-систем лучше использовать плагины для очистки или написать кастомный скрипт через ScriptRunner.

Очистка логов и аудита

Jira накапливает логи аудита и изменений. Для активных инстансов это могут быть гигабайты данных.

Таблица changegroup и changeitem

Эти таблицы хранят историю всех изменений в задачах. Со временем они могут стать очень большими. Можно очистить старые записи (например, старше 2 лет), но нужно быть осторожным — это история изменений.

Рекомендую сначала архивировать данные, а затем удалять. Или использовать настройки Jira для автоматической очистки старых логов аудита (если они есть).

Оптимизация индексов

Индексы — критический компонент производительности. Регулярная оптимизация индексов помогает поддерживать скорость работы.

Перестроение индексов

После большого количества операций INSERT/UPDATE индексы могут фрагментироваться. Перестроение индексов (REINDEX) помогает оптимизировать их.

Для PostgreSQL:

REINDEX DATABASE jira;

Или для конкретной таблицы:

REINDEX TABLE jiraissue;

Важно: REINDEX блокирует таблицы на время перестроения. Для больших таблиц это может занять много времени. Делайте это в нерабочее время или используйте CONCURRENTLY (PostgreSQL 12+):

REINDEX TABLE CONCURRENTLY jiraissue;

Анализ индексов

Не все индексы используются. Неиспользуемые индексы замедляют операции INSERT/UPDATE, но не ускоряют SELECT. Найти неиспользуемые индексы:

SELECT 
    schemaname,
    tablename,
    indexname,
    idx_scan
FROM pg_stat_user_indexes
WHERE schemaname = 'public' AND idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;

Если индекс не используется долгое время (например, более 6 месяцев), можно рассмотреть его удаление. Но делайте это осторожно — возможно, он нужен для редких запросов.

Обновление статистики

Оптимизатор запросов использует статистику о распределении данных в таблицах для выбора оптимальных планов выполнения. Устаревшая статистика приводит к неоптимальным планам и медленным запросам.

ANALYZE для PostgreSQL

Для PostgreSQL нужно регулярно запускать ANALYZE:

ANALYZE;

Или для конкретной таблицы:

ANALYZE jiraissue;

PostgreSQL обычно делает ANALYZE автоматически через autovacuum, но для больших таблиц это может происходить недостаточно часто. Рекомендую запускать ANALYZE вручную после больших изменений данных.

ANALYZE TABLE для MySQL

Для MySQL аналогичная команда:

ANALYZE TABLE jiraissue;

VACUUM для PostgreSQL

VACUUM — это специфичная для PostgreSQL операция, которая очищает "мёртвые" строки и освобождает место. PostgreSQL делает VACUUM автоматически через autovacuum, но для активных систем может потребоваться ручной VACUUM.

VACUUM ANALYZE jiraissue;

VACUUM FULL полностью переписывает таблицу и освобождает место на диске, но блокирует таблицу. Используйте только если действительно нужно освободить место.

Очистка attachments

Если attachments хранятся в файловой системе (а не в БД), их очистка — это отдельная задача. Но в базе данных остаются записи о attachments даже после удаления файлов.

Проверьте таблицу fileattachment на записи, которые ссылаются на несуществующие файлы, и удалите их (осторожно, с бэкапом).

Автоматизация обслуживания

Обслуживание базы данных должно быть автоматизировано. Создайте скрипты и cron-задачи для регулярного выполнения операций.

Ежедневные задачи

  • ANALYZE (для обновления статистики)
  • VACUUM (для PostgreSQL, если нужно)

Еженедельные задачи

  • Проверка размера таблиц
  • Проверка неиспользуемых индексов
  • Анализ медленных запросов

Ежемесячные задачи

  • REINDEX критичных таблиц (если нужно)
  • Анализ и очистка удалённых объектов
  • Архивация старых логов

Мониторинг производительности

После оптимизации важно отслеживать результаты и продолжать мониторинг.

Метрики для отслеживания

  • Размер базы данных — должен расти пропорционально количеству задач
  • Время выполнения типичных запросов — не должно увеличиваться
  • Фрагментация индексов — должна оставаться на низком уровне
  • Статистика использования таблиц — помогает выявить проблемы

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

Вот ошибки, которые я часто вижу при обслуживании БД:

Ошибка 1: Игнорирование обслуживания

Многие администраторы игнорируют обслуживание БД до тех пор, пока производительность не упадёт критично. Регулярное обслуживание предотвращает проблемы.

Ошибка 2: Агрессивная очистка

Слишком агрессивная очистка может удалить данные, которые нужны. Всегда архивируйте перед удалением и тестируйте процедуры очистки.

Ошибка 3: REINDEX в рабочее время

REINDEX блокирует таблицы. Делайте это в нерабочее время или используйте CONCURRENTLY.

Выводы

Регулярное обслуживание базы данных критично для поддержания производительности Jira. Начинайте с анализа текущего состояния: размер таблиц, фрагментация индексов, статистика использования.

Автоматизируйте регулярные операции: ANALYZE, VACUUM (для PostgreSQL), проверка размеров. Периодически делайте более глубокую оптимизацию: REINDEX, очистка удалённых объектов, архивация старых данных.

Мониторьте результаты и корректируйте процедуры обслуживания в зависимости от характеристик вашего инстанса. Каждый инстанс уникален и требует индивидуального подхода.

Если нужна помощь с оптимизацией базы данных — свяжитесь со мной.