Материалы / Истории / Кладбище забытых индексов
История

Кладбище забытых индексов

История о поиске неиспользуемых индексов через pg_stat_user_indexes и аккуратном освобождении дискового места в PostgreSQL.

— Ну что, Вася, три недели прошло. Диски вашей базе уже добавили? — Макс усмехнулся, откидываясь на спинку кресла.

Вася горько вздохнул:

— Ха-ха. Прикинь, до какого маразма довели: наша заявка уже вторую неделю находится на согласовании у инфобеза. Видимо оценивают, как добавление дисков к базе отчётности привлечёт внимание хакерских группировок.

Макс покачал головой:

— А свободное место на диске как было, так и осталось на грани?

— Да, и постоянно уменьшается, — Вася выдохнул. — Но я уже не удивляюсь. Помню, как в прошлом году месяц пытался получить права на просмотр логов. До сих пор помню эти бессмысленные переписки и анкеты. А потом вдруг у какого-то начальника не сформировался отчёт, подняли шум, и доступ предоставили за 15 минут.

Макс усмехнулся:

— А ты до сих пор это помнишь. Ну, тогда не удивляйся, что у твоей базы тоже столько мёртвых индексов. Она ведь тоже не забывает, что когда-то их создали.

— Мёртвых? — Вася нахмурился. — Что ты имеешь в виду?

— Когда я изучал, что у вас там занимает место, заметил, что у многих таблиц по 10 и больше индексов. Я понимаю, что отчётность, аналитика и всё такое, но это выглядит сильно избыточным. Напомни, у вас статистику использования объектов давно сбрасывали?

— Точно не помню… Кажется, пару месяцев назад, после последнего перезапуска базы.

— А мы можем посмотреть, — вспомнил Макс и развернул ноутбук.

SELECT datname, stats_reset
FROM pg_stat_database;

— Действительно два с половиной месяца, этого уже вполне достаточно. Смотри сюда.

Макс открыл скрипт.

SELECT
s.schemaname,
s.relname AS table_name,
s.indexrelname AS index_name,
s.idx_scan AS index_scans,
pg_size_pretty(pg_relation_size(s.indexrelid)) AS index_size,
pg_get_indexdef(s.indexrelid) AS index_definition,
i.indisvalid,
i.indisprimary
FROM pg_stat_user_indexes s
JOIN pg_index i ON i.indexrelid = s.indexrelid
WHERE s.idx_scan = 0
ORDER BY pg_relation_size(s.indexrelid) DESC;

— Этот запрос покажет все индексы, по которым не было index scan с момента последнего сброса накопительной статистики. Только не спеши их удалять.

— Это почему ещё? — Вася выглядел так, будто только что осознал, что у него в квартире поселился ненужный сосед.

— Ну всё же надо посмотреть на каждый индекс внимательно. Индекс может быть нужен для PRIMARY KEY, UNIQUE и так далее. Лучше подготовить список для удаления и разослать коллегам на согласование. Чтобы не бегали потом с криками «Кто удалил? Прибью когда найду!»

Вася кивнул:

— Спасибо! Теперь у меня есть новая цель.

Они вместе задумчиво посмотрели на результаты запроса. Макс усмехнулся:

— Ну что, Вася, видишь, сколько мёртвого груза в базе накопилось?

— Угу, — кивнул Вася. — Кто бы мог подумать, что забытые и никому не нужные индексы занимают столько места.

Макс отставил кружку на стол и потянулся:

— Да, всё как в жизни. Мы с возрастом тоже так накапливаем. Вроде бы тащим с собой какие-то обиды, надежды, представления о том, как должно быть. Кажется, что это важно, но на деле — только место занимает.

Он постучал по экрану:

— Поэтому иногда полезно пересмотреть то, что давно кажется «устоявшимся». Избавиться от того, что на самом деле уже мешает. Базу — от ненужных индексов. А себя — от старых фантазий и обид.

Публикация в Telegram