REINDEX#
REINDEX
REINDEX — перестроить индексы
Синтаксис
REINDEX [ (option
[, ...] ) ] { INDEX | TABLE | SCHEMA } [ CONCURRENTLY ]name
REINDEX [ (option
[, ...] ) ] { DATABASE | SYSTEM } [ CONCURRENTLY ] [name
] whereoption
can be one of: CONCURRENTLY [boolean
] TABLESPACEnew_tablespace
VERBOSE [boolean
]
Описание
REINDEX
перестраивает индекс, используя данные, хранящиеся в таблице индекса, заменяя старую копию индекса. Существует несколько сценариев, в которых следует использовать REINDEX
:
Индекс был поврежден и больше не содержит действительных данных. Хотя в теории это никогда не должно происходить, на практике индексы могут быть повреждены из-за ошибок программного обеспечения или сбоев оборудования.
REINDEX
предоставляет метод восстановления.Индекс стал “раздутым”, то есть он содержит много пустых или почти пустых страниц. Это может произойти с индексами B-дерева в Tantor SE-1C при определенных нестандартных сценариях доступа.
REINDEX
предоставляет способ уменьшить потребление пространства индексом путем записи новой версии индекса без мертвых страниц. См. Раздел 23.2 для получения дополнительной информации.Вы изменили параметр хранения (например, fillfactor) для индекса и хотите убедиться, что изменение полностью вступило в силу.
Если построение индекса с опцией
CONCURRENTLY
завершается неудачно, этот индекс остается “недействительным”. Такие индексы бесполезны, но удобно использоватьREINDEX
для их перестроения. Обратите внимание, что толькоREINDEX INDEX
может выполнять параллельное построение на недействительном индексе.
Параметры
INDEX
Пересоздать указанный индекс. Эта форма команды
REINDEX
не может быть выполнена внутри блока транзакции при использовании с секционированным индексом.TABLE
Пересоздает все индексы указанной таблицы. Если у таблицы есть вторичная таблица “TOAST”, она также переиндексируется. Эта форма команды
REINDEX
не может быть выполнена внутри блока транзакции при использовании с секционированной таблицей.SCHEMA
Пересоздает все индексы указанной схемы. Если у таблицы этой схемы есть вторичная таблица “TOAST”, она также переиндексируется. Также обрабатываются индексы на общих системных каталогах. Эта форма команды
REINDEX
не может быть выполнена внутри блока транзакции.DATABASE
Воссоздать все индексы в текущей базе данных, за исключением системных каталогов. Индексы на системных каталогах не обрабатываются. Эта форма
REINDEX
не может быть выполнена внутри блока транзакции.SYSTEM
Пересоздать все индексы на системных каталогах в текущей базе данных. Индексы на общих системных каталогах включены. Индексы на пользовательских таблицах не обрабатываются. Эта форма команды
REINDEX
не может быть выполнена внутри блока транзакции.name
Имя конкретного индекса, таблицы или базы данных, которую необходимо переиндексировать. Имена индексов и таблиц могут быть квалифицированы схемой. В настоящее время,
REINDEX DATABASE
иREINDEX SYSTEM
могут переиндексировать только текущую базу данных. Их параметр является необязательным, и он должен совпадать с именем текущей базы данных.CONCURRENTLY
Когда используется эта опция, Tantor SE-1C будет перестраивать индекс без блокировки, которая препятствует одновременным вставкам, обновлениям или удалениям в таблице; в то время как стандартная перестройка индекса блокирует записи (но не чтение) в таблице до ее завершения. Существует несколько оговорок, о которых следует знать при использовании этой опции — см. Rebuilding Indexes Concurrently ниже.
Для временных таблиц
REINDEX
всегда является непараллельной операцией, так как другая сессия не может к ним обратиться, и непараллельная переиндексация менее затратна.TABLESPACE
Указывает, что индексы будут перестроены в новом табличном пространстве.
VERBOSE
Печатает отчет о ходе выполнения каждого переиндексированного индекса.
boolean
Определяет, должна ли быть включена или выключена выбранная опция. Вы можете написать
TRUE
,ON
или1
, чтобы включить опцию, иFALSE
,OFF
или0
, чтобы отключить ее. Значениеboolean
также можно опустить, в этом случае предполагаетсяTRUE
.new_tablespace
Табличное пространство имен, в котором будут перестроены индексы.
Примечания
Если вы подозреваете повреждение индекса на пользовательской таблице, вы можете просто перестроить этот индекс или все индексы на таблице, используя REINDEX INDEX
или REINDEX TABLE
.
Вещи становятся более сложными, если вам нужно восстановиться после повреждения индекса в системной таблице. В этом случае важно, чтобы система сама не использовала ни одного из подозрительных индексов. (Действительно, в таком сценарии вы можете обнаружить, что серверные процессы немедленно вылетают при запуске из-за зависимости от поврежденных индексов). Чтобы безопасно восстановиться, сервер должен быть запущен с опцией -P
, которая предотвращает использование индексов для поиска в системном каталоге.
Один из способов сделать это - выключить сервер и запустить однопользовательский сервер Tantor SE-1C с опцией -P
включенной в его командной строке. Затем можно выполнить команды REINDEX DATABASE
, REINDEX SYSTEM
, REINDEX TABLE
или REINDEX INDEX
, в зависимости от того, сколько нужно восстановить. Если сомневаетесь, используйте REINDEX SYSTEM
для выбора восстановления всех системных индексов в базе данных. Затем завершите сессию однопользовательского сервера и перезапустите обычный сервер. Дополнительную информацию о взаимодействии с интерфейсом однопользовательского сервера см. на странице postgres.
Альтернативно, обычная сессия сервера можно запустить с опцией -P
включенной в командной строке. Метод для этого различается в разных клиентах, но во всех клиентах, основанных на libpq, можно установить переменную окружения PGOPTIONS
в значение -P
перед запуском клиента. Обратите внимание, что хотя этот метод не требует блокировки других клиентов, все же может быть разумно предотвратить подключение других пользователей к поврежденной базе данных до завершения ремонтных работ.
REINDEX
похож на удаление и повторное создание индекса, поскольку содержимое индекса перестраивается с нуля. Однако, блокировка учитывается по-другому. REINDEX
блокирует записи, но не чтение родительской таблицы индекса. Он также берет эксклюзивную блокировку ACCESS EXCLUSIVE
на обрабатываемый индекс, что блокирует чтение, пытающееся использовать этот индекс. В частности, планировщик запросов пытается взять блокировку ACCESS SHARE
на каждый индекс таблицы, независимо от запроса, поэтому REINDEX
блокирует практически любые запросы, кроме некоторых подготовленных запросов, план которых был закеширован и которые не используют этот самый индекс. В отличие от этого, DROP INDEX
мгновенно берет эксклюзивную блокировку ACCESS EXCLUSIVE
на родительскую таблицу, блокируя как запись, так и чтение. Последующий CREATE INDEX
блокирует записи, но не чтение; поскольку индекса нет, ни одно чтение не будет пытаться его использовать, что означает, что блокировки не будет, но чтение может быть принудительно переведено в дорогостоящие последовательные сканирования.
Для переиндексации отдельного индекса или таблицы необходимо быть владельцем этого индекса или таблицы. Для переиндексации схемы или базы данных необходимо быть владельцем этой схемы или базы данных. Обратите внимание, что это означает, что непривилегированные пользователи могут перестраивать индексы таблиц, принадлежащих другим пользователям. Однако, как особое исключение, когда непривилегированный пользователь выполняет команду REINDEX DATABASE
, REINDEX SCHEMA
или REINDEX SYSTEM
, индексы на общих каталогах будут прне указаны, если пользователь не является владельцем каталога (что обычно не будет иметь место). Конечно, суперпользователи всегда могут переиндексировать что угодно.
Переиндексация секционированных индексов или секционированных таблиц поддерживается с помощью команды REINDEX INDEX
или REINDEX TABLE
соответственно. Каждая секция указанного секционированного отношения переиндексируется в отдельной транзакции. Эти команды не могут использоваться внутри блока транзакции при работе с секционированной таблицей или индексом.
При использовании ключевого слова TABLESPACE
с командой REINDEX
для индекса или таблицы с секционированием, обновляются только ссылки на табличное пространство листовых секций. Поскольку секционированные индексы не обновляются, рекомендуется отдельно использовать команду ALTER TABLE ONLY
для них, чтобы новые присоединенные секции наследовали новое табличное пространство. В случае сбоя, возможно, не все индексы будут перемещены в новое табличное пространство. Повторное выполнение команды перестроит все листовые секции и переместит ранее необработанные индексы в новое табличное пространство.
Если используется SCHEMA
, DATABASE
или SYSTEM
с TABLESPACE
, системные отношения будут прне указаны и будет сгенерировано одно WARNING
. Индексы на TOAST-таблицах будут перестроены, но не перемещены в новое табличнoe пространствo.
Перестроение индексов одновременно
Перестроение индекса может помешать нормальной работе базы данных. Обычно Tantor SE-1C блокирует таблицу, индекс которой перестраивается, от записи и выполняет полное построение индекса с одним проходом по таблице. Другие транзакции все еще могут читать таблицу, но если они попытаются вставить, обновить или удалить строки в таблице, они будут заблокированы до завершения перестроения индекса. Это может серьезно повлиять на систему, если она является живой производственной базой данных. Очень большие таблицы могут занимать много часов для индексации, и даже для меньших таблиц перестроение индекса может блокировать запись на промежутки времени, которые неприемлемо долги для производственной системы.
Tantor SE-1C поддерживает перестроение индексов с минимальной блокировкой записей. Этот метод вызывается с указанием опции CONCURRENTLY
команды REINDEX
. При использовании этой опции Tantor SE-1C должен выполнить два сканирования таблицы для каждого индекса, который требуется перестроить, и дождаться завершения всех существующих транзакций, которые могут потенциально использовать индекс. Этот метод требует больше общей работы, чем стандартное перестроение индекса, и занимает значительно больше времени для завершения, так как он должен ждать незавершенных транзакций, которые могут изменять индекс. Однако, поскольку он позволяет продолжать нормальные операции во время перестроения индекса, этот метод полезен для перестроения индексов в производственной среде. Конечно, дополнительная нагрузка на ЦП, память и ввод-вывод, вызванная перестроением индекса, может замедлить другие операции.
Следующие шаги выполняются во время параллельной переиндексации. Каждый шаг выполняется в отдельной транзакции. Если требуется перестроить несколько индексов, то каждый шаг проходит по всем индексам перед переходом к следующему шагу.
В каталог добавляется новое временное определение индекса
pg_index
. Это определение будет использоваться для замены старого индекса. Также на индексы, которые переиндексируются, а также на связанные с ними таблицы, берется блокировкаSHARE UPDATE EXCLUSIVE
на уровне сессии, чтобы предотвратить любые изменения схемы во время обработки.В первом проходе для каждого нового индекса выполняется построение индекса. После построения индекса его флаг
pg_index.indisready
переключается в значение “true”, чтобы сделать его готовым для вставки и видимым для других сессий после завершения транзакции, выполнившей построение. Этот шаг выполняется в отдельной транзакции для каждого индекса.Затем выполняется второй проход для добавления кортежей, которые были добавлены во время выполнения первого прохода. Этот шаг также выполняется в отдельной транзакции для каждого индекса.
Все ограничения, которые ссылались на индекс, изменяются так, чтобы ссылаться на новое определение индекса, и меняются имена индексов. На этом этапе
pg_index.indisvalid
переключается на “true” для нового индекса и на “false” для старого, и выполняется недействительность кеша, что приводит к недействительности всех сессий, которые ссылались на старый индекс.Все старые индексы переключены на
pg_index.indisready
в значение “false”, чтобы предотвратить вставку новых кортежей после ожидания завершения выполняющихся запросов, которые могут ссылаться на старый индекс.Все старые индексы удаляются. Блокировки сессий
SHARE UPDATE EXCLUSIVE
для индексов и таблицы снимаются.
Если возникает проблема при перестроении индексов, такая как нарушение уникальности в уникальном индексе, команда REINDEX
завершится неудачей, но оставит недействительный новый индекс в дополнение к уже существующему. Этот индекс будет игнорироваться для целей запросов, поскольку он может быть неполным; однако он все равно будет потреблять издержки на обновление. Команда psql \d
будет отображать такой индекс как INVALID
:
postgres=# \d tab Table "public.tab" Column | Type | Modifiers --------+---------+----------- col | integer | Indexes: "idx" btree (col) "idx_ccnew" btree (col) INVALID
Если индекс, помеченный INVALID
, имеет суффикс ccnew
, то это соответствует временному индексу, созданному во время параллельной операции, и рекомендуется восстановить его, используя DROP INDEX
, а затем повторить REINDEX CONCURRENTLY
.
Если недействительный индекс вместо этого имеет суффикс ccold
, это соответствует исходному индексу, который не может быть удален; рекомендуется просто удалить этот индекс, поскольку правильная перестройка была успешной.
Создание обычных индексов позволяет одновременное выполнение других обычных индексов на той же таблице, но одновременное создание индекса в режиме параллельного выполнения может происходить только для одной таблицы за раз. В обоих случаях недопустимы другие типы модификации схемы таблицы в то же время. Еще одно отличие заключается в том, что команда REINDEX TABLE
или REINDEX INDEX
может выполняться внутри блока транзакции, но команда REINDEX CONCURRENTLY
не может.
Как и любая долговременная транзакция, REINDEX
на таблице
может повлиять на то, какие кортежи могут быть удалены параллельно
VACUUM
на любой другой таблице.
REINDEX SYSTEM
не поддерживает
CONCURRENTLY
, так как системные каталоги не могут быть переиндексированы
одновременно.
Кроме того, индексы для ограничений-исключений не могут быть переиндексированы одновременно. Если такой индекс указан непосредственно в этой команде, будет вызвана ошибка. Если таблица или база данных с индексами ограничений-исключений переиндексируется одновременно, эти индексы будут прне указаны. (Возможно переиндексировать такие индексы без опции CONCURRENTLY
).
Каждый запущенный бэкенд, выполняющий команду REINDEX
, будет отображать прогресс в представлении pg_stat_progress_create_index
. Подробности см. в разделе Раздел 26.4.4.
Примеры
Перестроить один индекс:
REINDEX INDEX my_index;
Перестроить все индексы на таблице my_table
:
REINDEX TABLE my_table;
Перестроить все индексы в определенной базе данных, не доверяя системным индексам, которые уже могут быть действительными:
$export PGOPTIONS="-P"
$psql broken_db
... broken_db=> REINDEX DATABASE broken_db; broken_db=> \q
Перестроить индексы для таблицы без блокировки операций чтения и записи на связанных отношениях во время выполнения переиндексации:
REINDEX TABLE CONCURRENTLY my_broken_table;
Совместимость
В стандарте SQL нет команды REINDEX
.