pg_repack

Синтаксис

pg_repack [параметр]... [имя_бд]

Описание

pg_repack — это расширение QHB, которое позволяет избавляться от «разбухания» таблиц и индексов и при необходимости восстанавливать физический порядок кластеризованных индексов. В отличие от команд CLUSTER и VACUUM FULL, оно делает это в реальном времени, не удерживая эксклюзивную блокировку обрабатываемых таблиц во время обработки. Кроме того, pg_repack очень эффективно, его производительность сравнима с прямым использованием CLUSTER.

Для реорганизации таблиц можно выбрать один из следующих способов:

  • Выполнение неблокирующей CLUSTER (упорядочивание по кластерному индексу);
  • Упорядочивание по указанным столбцам;
  • Выполнение неблокирующей VACUUM FULL (упаковка только строк);
  • Перестройка или перемещение только индексов таблицы.

Примечание
Использовать утилиту могут только суперпользователи. Целевая таблица должна иметь первичный ключ (PRIMARY KEY) или хотя бы уникальный индекс (UNIQUE) для столбца NOT NULL.


Требования

Версия QHB 1.5.1 и выше.

Диски: Для полной перепаковки таблиц требуется свободное место на диске размером примерно в два раза больше, чем занимает целевая таблица (или таблицы) и ее индексы. Например, если общий размер реорганизуемых таблиц и индексов составляет 1 ГБ, потребуется дополнительно 2 ГБ дискового пространства.


Установка

Модуль реорганизации таблиц с минимальными блокировками для QHB поставляется в виде пакета qhb-1.5.2-pg-repack.

Подключите репозиторий пакетов QHB и установите пакет расширения для выбранной платформы со страницы загрузки.

После установки загрузите расширение pg_repack в базу данных, которую необходимо обработать. pg_repack упакован как расширение, поэтому надо запустить команду:

$ psql -c "CREATE EXTENSION pg_repack" -d ваша_бд

Удалить pg_repack можно с помощью команды DROP EXTENSION pg_repack или просто удалив схему repack.

При обновлении с предыдущей версии pg_repack просто удалите старую версию из базы данных, как описано выше, и установите новую версию.


Параметры

Параметры реорганизации

-a
--all
Попытаться перепаковать все базы данных кластера. Базы данных, в которых не установлено расширение pg_repack, будут пропущены.

-t таблица
--table=таблица
Реорганизовать только указанные таблицы. Реорганизовать несколько таблиц можно, написав несколько ключей -t. По умолчанию реорганизуются все подходящие таблицы в целевых базах данных.

-I таблица
--parent-table=таблица Реорганизовать как указанные таблицы, так и их наследников. Реорганизовать несколько иерархий таблиц можно, написав несколько ключей -I.

-c схема
--schema=схема
Перепаковать таблицы только в указанной схеме (схемах). Перепаковать несколько схем можно, написав несколько ключей -c. Можно использовать вместе с --tablespace для перемещения таблиц в другое табличное пространство.

-o столбец [,...]
--order-by=столбец [,...]
Выполнить неблокирующую кластеризацию (CLUSTER), с упорядочиванием по указанным столбцам.

-n
--no-order
Выполнить неблокирующую полную очистку (VACUUM FULL). Это значение по умолчанию для некластеризованных таблиц.

-N
--dry-run
Показать, что будет перепаковано и завершиться.

-j
--jobs
Создать указанное количество дополнительных подключений к QHB и использовать эти дополнительные подключения для распараллеливания перестройки индексов для каждой таблицы. Параллельное построение индексов поддерживается только для полной перепаковки таблиц, без параметров --index или --only- indexes. Если на сервере QHB есть дополнительные ядра и дисковый ввод-вывод, это может быть полезным способом ускорить pg_repack.

-s табличное_пространство
--tablespace=табличное_пространство
Переместить перепакованные таблицы в указанное табличное пространство: по сути, это неблокирующая версия ALTER TABLE ... SET TABLESPACE. Индексы таблиц остаются в исходном табличном пространстве, если только дополнительно не указан параметр --moveidx.

-S
--moveidx
Переместить индексы перепакованных таблиц в табличное пространство, указанное параметром --tablespace.

-i индекс
--index=индекс
Перепаковать только указанный индекс (индексы). Перепаковать несколько индексов можно, написав несколько ключей -i. Может использоваться вместе с --tablespace для перемещения индекса(ов) в другое табличное пространство.

-x
--only-indexes
Перепаковать только индексы таблицы (таблиц), указанной в параметре --table или --parent-table.

-T сек
--wait-timeout=сек
Расширению pg_repack нужно получить эксклюзивную блокировку в конце реорганизации. Этот параметр определяет, сколько секунд pg_repack будет ждать, чтобы получить эту блокировку. Если блокировку не удастся получить по истечении этого времени и параметр --no-kill-backend не указан, pg_repack принудительно отменит конфликтующие запросы. pg_repack прибегнет к вызову pg_terminate_backend() для отключения всех оставшихся серверных процессов, после того как этот срок пройдет дважды. Значение по умолчанию — 60 секунд.

-D
--no-kill-backend
Если блокировка не может быть снята на время, указанное в --wait-timeout, вместо отмены конфликтующих запросов перейти к перепаковке таблицы. Значение по умолчанию — false.

-Z
--no-analyze
Не выполнять ANALYZE после полной реорганизации таблицы. Если этот ключ не указан, после реорганизации выполняется ANALYZE.

-k
--no-superuser-check
Пропустить проверки суперпользователя на стороне клиента. Этот параметр полезен для использования pg_repack на платформах, поддерживающих запуск от имени пользователя без прав суперпользователя.

-C
--exclude-extension
Не перепаковывать таблицы, принадлежащие конкретному расширению. Некоторые расширения могут сильно зависеть от таких таблиц во время планирования и т. д.


Параметры подключения

Примечание
Параметры -all и --dbname, или --table, или --parent-table нельзя использовать одновременно.

-a
--all
Реорганизовать все базы данных.

-d имя_бд
--dbname=имя_бд
Задает имя реорганизуемой базы данных. Если этот параметр не указан и не используется -a (или --all), имя базы данных считывается из переменной среды PGDATABASE. Если этот параметр не установлен, используется имя пользователя, указанное для подключения.

-h имя_хоста
--host=имя_хоста
Указывает имя хост-компьютера, на котором работает сервер. Если значение начинается со слэша, оно используется в качестве каталога для сокета домена Unix.

-p порт
--port=порт
Указывает TCP-порт или расширение файла локального сокета домена Unix, через который сервер принимает подключения.

-U имя_пользователя
--username=имя_пользователя
Имя пользователя, под которым производится подключение.

-w
--no-password
Никогда не запрашивать ввод пароля. Если серверу требуется аутентификация по паролю, и пароль недоступен с помощью иных средств, таких как файл .pgpass, попытка подключения завершится неудачно. Этот параметр может быть полезен в пакетных заданиях и скриптах, где нет пользователя, чтобы ввести пароль.

-W
--password
Принудительно запрашивать пароль перед подключением к базе данных.
Это несущественный параметр, так как pg_repack автоматически запросит пароль, если сервер требует аутентификацию по паролю. Однако чтобы выяснить это, pg_repack потребуется дополнительная попытка подключения к серверу. В некоторых случаях имеет смысл ввести -W, чтобы исключить эту лишнюю попытку.


Общие параметры

-e
--echo
Отобразить на экране команды, которые pg_repack генерирует и отправляет на сервер.

-E уровень
--elevel=уровень
Выбрать уровень выводимых сообщений: DEBUG, INFO, NOTICE, WARNING, ERROR, LOG, FATAL и PANIC. Уровень по умолчанию — INFO.

--help
Показать справку об аргументах командной строки pg_repack и завершиться.

--version
Вывести версию pg_repack и завершиться.


Переменные среды

PGDATABASE
PGHOST
PGPORT
PGUSER
Параметры подключения по умолчанию.

Эта утилита, как и большинство других утилит QHB, также использует переменные среды, поддерживаемые libpq (см. раздел Переменные среды).


Примеры

Выполнить неблокирующую команду CLUSTER всех кластеризованных таблиц в базе данных test и выполнить неблокирующую команду VACUUM FULL всех некластеризованных таблиц:

$ pg_repack test

Выполнить неблокирующую команду VACUUM FULL для таблиц foo и bar в базе данных test (кластерные индексы, если таковые имеются, игнорируется):

$ pg_repack --no-order --table foo --table bar test

Переместить все индексы таблицы foo в табличное пространство tbs:

$ pg_repack -d test --table foo --only-indexes --tablespace tbs

Переместить указанный индекс в табличное пространство tbs:

$ pg_repack -d test --index idx --tablespace tbs

Диагностика

Сообщения об ошибках выводятся при сбое pg_repack. В следующем списке показаны причины ошибок.

После фатальных ошибок потребуется очистка вручную. Для этого просто удалите pg_repack из базы данных и заново его установите. Выполните

DROP EXTENSION pg_repack CASCADE

в базе данных, где произошла ошибка, а затем выполните

CREATE EXTENSION pg_repack
INFO: database "db" skipped: pg_repack VER is not installed in the database
-- ИНФО: база данных "db" пропущена: в этой базе данных не установлено pg_repack VER

Если указан параметр --all, pg_repack в базе данных не устанавливается.

Создайте расширение pg_repack в базе данных.

ERROR: pg_repack VER is not installed in the database
-- ОШИБКА: в этой базе данных не установлено pg_repack VER

pg_repack не установлено в базе данных, указанной в параметре --dbname.

Создайте расширение pg_repack в базе данных.

ERROR: program 'pg_repack V1' does not match database library 'pg_repack V2'
-- ОШИБКА: программа 'pg_repack V1' не соответствует библиотеке базы данных 'pg_repack V2'

Существует несоответствие между двоичным файлом pg_repack и библиотекой базы данных (.so или .dll).

Несоответствие может быть связано с неправильным двоичным файлом в $PATH или обращением к неправильной базе данных. Проверьте каталог программы и базу данных; если они соответствуют ожиданиям, возможно, вам потребуется повторить установку pg_repack.

ERROR: extension 'pg_repack V1' required, found 'pg_repack V2'
-- ОШИБКА: требуется расширение 'pg_repack V1', найдено 'pg_repack V2'

Расширение SQL, найденное в базе данных, не соответствует версии, требуемой программой pg_repack.

Необходимо удалить расширение из базы данных и перезагрузить его, как описано в разделе Установка.

ERROR: relation "table" must have a primary key or not-null unique keys
-- ОШИБКА: отношение "table" должно иметь первичный ключ или уникальные ключи, отличные от NULL

Для целевой таблицы не определено ограничение PRIMARY KEY или какие-либо ограничения UNIQUE.

Определите для таблицы ограничение PRIMARY KEY или UNIQUE.

ERROR: query failed: ERROR: column "col" does not exist
-- ОШИБКА: запрос не выполнен: ОШИБКА: столбец "col" не существует

В целевой таблице нет столбцов, указанных в параметре --order-by.

Укажите существующие столбцы.

WARNING: the table "tbl" already has a trigger called repack_trigger
-- ПРЕДУПРЕЖДЕНИЕ: у таблицы "tbl" уже имеется триггер с именем repack_trigger

Этот триггер, вероятно, был установлен во время предыдущей попытки запуска pg_repack для таблицы, которая была прервана и по какой-то причине не смогла удалить временные объекты.

Удалить все временные объекты можно, удалив и заново создав расширение: подробную информацию см. в разделе Установка.

ERROR: Another pg_repack command may be running on the table. Please try again later.
-- ОШИБКА: Возможно, для этой таблицы уже выполняется другая команда pg_repack.
-- Пожалуйста, повторите попытку позднее.

Когда на одной таблице выполняются две параллельные команды pg_repack, существует вероятность взаимоблокировки. Поэтому попробуйте запустить команду через некоторое время.

WARNING: Cannot create index "schema"."index_xxxx", already exists
DETAIL: An invalid index may have been left behind by a previous pg_repack on the
table which was interrupted. Please use DROP INDEX "schema"."index_xxxxx" to remove
this index and try again.
-- ПРЕДУПРЕЖДЕНИЕ: Невозможно создать уже существующий индекс "schema"."index_xxxx"
-- ПОДРОБНЕЕ: Недопустимый индекс мог быть оставлен при предыдущем выполнении
-- pg_repack для таблицы, которое было прервано. Пожалуйста, воспользуйтесь
-- DROP INDEX "schema"."index_xxxxx", чтобы удалить этот индекс, и повторите попытку.

Был оставлен временный индекс, явно созданный при предыдущем выполнении pg_repack, и не стоит рисковать, удаляя его самостоятельно. Если этот индекс действительно был создан при предыдущем запуске pg_repack, после которого не была проведена очистка, следует просто выполнить DROP INDEX и повторить команду repack.


Ограничения

Расширение pg_repack имеет следующие ограничения:

  • pg_repack не может реорганизовать временные таблицы.

  • pg_repack не может кластеризовать таблицы по индексам GiST.

  • Пока выполняется pg_repack, вы не сможете выполнять команды DDL для целевых таблиц, за исключением VACUUM или ANALYZE. Чтобы обеспечить соблюдение этого ограничения, pg_repack будет удерживать блокировку ACCESS SHARE для целевой таблицы во время ее полной перепаковки.


Детализация

Полная перепаковка таблицы

Чтобы выполнить полную перепаковку таблицы, pg_repack:

  1. создает таблицу журнала для записи изменений, внесенных в исходную таблицу;
  2. добавляет триггер в исходную таблицу, для регистрации команд INSERT, UPDATE и DELETE в таблице журнала;
  3. создает новую таблицу, содержащую все строки из старой таблицы;
  4. строит индексы в этой новой таблице;
  5. применяет все изменения, которые произошли в таблице журнала, к новой таблице;
  6. меняет местами таблицы, включая индексы и всплывающие таблицы, используя системные каталоги;
  7. удаляет исходную таблицу.

pg_repack будет удерживать блокировку ACCESS EXCLUSIVE только в течение короткого периода времени во время первоначальной настройки (шаги 1 и 2) и на заключительном этапе обмена и удаления (шаги 6 и 7). В остальное время pg_repack нужно удерживать только блокировку ACCESS SHARE для исходной таблицы, что означает, что операции INSERT, UPDATE и DELETE могут выполняться как обычно.


Перепаковка только индексов

Чтобы выполнить перепаковку только для индекса, pg_repack проводит следующие операции:

  1. создает новые индексы в таблице, используя сопоставление CONCURRENTLY определений старых индексов;
  2. заменяет в каталогах старые индексы на новые;
  3. удаляет старые индексы.

Одновременное создание индексов осуществляется с несколькими оговорками; подробную информацию см. в параграфе Неблокирующее построение индексов на справочной странице команды CREATE INDEX.


См. также

Документация по pg_repack на Github, clusterdb, vacuumdb