PostgreSQL | Как обновить индекс?

PostgreSQL | Как обновить индекс?

Для обновления индекса нужно точно знать его имя и имя схемы данных. Таблица может содержать большое количество индексов, как по полным столбцам, так и по их частичным значениям (по диапазонам значений в столбце). Обновление индекса по сути является его полным перестроением. Можно сказать, что мы производим две операции:

  1. Удаляем существующий индекс совсем (удаляем только по готовности нового)
  2. Создаём новый индекс с тем же набором условий и именем как и был до этого.

Пример обновления:

REINDEX INDEX CONCURRENTLY scheme.index_name;

Мы используем слово REINDEX, чтобы сказать среде выполнения SQL кода, что мы хотим перестроить индекс.

После этого у нас есть несколько вариантов, что пере-индексировать:

  1. INDEX
  2. TABLE
  3. SCHEMA
  4. DATABASE
  5. SYSTEM

Нас интересует только перестроение одного конкретного индекса, поэтому мы выбираем слово INDEX, а не TABLE или другое.

Затем мы используем слово CONCURRENTLY, чтобы не блокировать таблицу от возможных вставок, удалений или обновлений записей. Так, мы в спокойном режиме перестроим индекс. Да, это дольше чем с блокировкой, но не вызовет проблем.

Общая идея перестроения индекса такова, что существующий индекс удалится только после полного созданного нового индекса. То есть, если что-то пойдёт не так во время переиндекса, то система откатится в обычное состояние к старому индексу так как он ещё не будет удалён к этому времени.

 

Зачем нужно обновлять (перестраивать / пересобирать) индекс в PostgreSQL?

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

Разработчики PostgreSQL ничего умнее чем «страницы» пока не придумали. Поэтому индексы также хранят информацию в страницах как и таблицы. То есть под капотом алгоритм «освежевания» страниц точно такой же для индексов, как и для таблиц.

Говоря простыми словами индекс не сильно заморачивается над оптимизацией свободного места и тупо «распухает». Так быстрее. Вы же не оглядываетесь назад, чтобы подсчитать свои шаги, когда куда-то идёте — так и тут.

 

Пример. Мы создали индекс для 1000 идентификаторов внешнего ключа. У нас это третья зависимая таблица в цепочке каскада. Работает каскадное удаление. Изначальный размер индекса 72 мегабайта. Индекс был создан за 1 минуту. Транзакций в базу не поступало.

После удаления около 1480000 записей (в том числе по каскаду) размер индекса не изменился.

Размер индекса до перестройки как и был изначально при создании - PostgreSQL
Размер индекса до перестройки как и был изначально при создании — PostgreSQL

 

Теперь делаем перестроение индекса и смотрим как поменяется его размер.

REINDEX INDEX CONCURRENTLY a.efim_index_t_all_dp_idd_k8747;

Время на перестроение индекса также заняло 1 минуту. Суммарно в таблице около 250 миллионов записей. Количество записей в пропорции не сильно изменилось, поэтому время практически тоже самое.

Размер индекса после перестройки существенно уменьшился - PostgreSQL
Размер индекса после перестройки существенно уменьшился — PostgreSQL

Самое главное то, что мы существенно уменьшаем размер индекса на диске. В нашем примере это уменьшение размера составило 15 процентов. С 71 до 61 мегабайта. Это очень существенно.

 

Информационные ссылки

Официальный сайт WEB-оболочки pgAdminhttps://www.pgadmin.org

Официальный сайт СУБД PostgreSQLhttps://www.postgresql.org

Команды SQLhttps://postgrespro.ru/docs/postgresql/15/sql-commands

Команда REINDEXhttps://postgrespro.ru/docs/postgresql/15/sql-reindex