Практически каждый из нас сталкивался с проблемой, что нужно добавить дополнительный индекс в таблицу на боевом проекте. При этом объем таблицы очень большой и индекс будет создаваться очень долго, а проект останавливать нельзя. Все ведь знают, что при создании индекса, таблица блокируется на изменения.
Для того, что бы как-то решить эту проблему в PostgreSQL были введено конкурентное создание индекса, которое позволяет создавать индекс без блокировки таблицы.
Казалось бы, вот оно счастье, но нет, обновление этого индеска требует двойного сканирования таблицы, плюс еще дополнительный процесс ввода / вывода требуется.
Использование
Допустим у нас есть таблица в которой есть очень большое количество записей, но нам неожиданно понадобился дополнительный индекс. Просто создаем индекс указав ему волшебное слово CONCURRENTLY
CREATE INDEX CONCURRENTLY
myindex
ON mytable
...
Что дальше? А дальше, индекс создается в фоновом режиме, при этом база будет естественно подтормаживать, но при этом работать штатно, то бишь, никаких ограничений.
Понятно, что индекс уже как бы создан, но использоваться он не будет, хотя в таблице присутсвует, правда с оговоркой, он будет помечен как INVALID, до тех пор пока не построится.
Postgres = # \d mytable
Table "public.mytable"
Column | Type | Modifiers
--------+---------+-----------
col | integer |
Indexes:
"myindex" btree (col) INVALID
После того, как его отпустит все будет хорошо.
Проблемы
Как можно догадаться, асинхронность не позволяет со стопроцентной уверенностью создавать уникальный индекс. Могут возникнуть ситуации, когда во время создания конкурентного индекса уникальность может быть нарушена. Как итог, создание обламывается и индекс остается инвалидом, причем в запросах он не участвует, но ресурсы ест.
Как быть если он таки обломался. Практически, никак, REINDEX нам не поможет, так как уникальность уже нарушена, остается только в ручную исправить уникальность, и создать индекс заново.
Дополнительно
Так же следует иметь ввиду, что создание конкурентного индекса невозможно в пределах транзакции, т.к. это нарушает её (транзакции) принцип.
Конкурентные индексы могут создаваться для выражений, а так же как частичные индексы.