pg_repack - Модуль реорганизации таблиц с минимальными блокировками

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

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

  • Онлайн КЛАСТЕР (упорядочивание по индексу кластера);
  • Упорядочивание по указанным столбцам;
  • Онлайн VACUUM FULL (упаковка только строк);
  • Перестройка или перемещение только индексов таблицы.

Примечание
Использовать утилиту могут только суперпользователи. Целевая таблица должна иметь ПЕРВИЧНЫЙ КЛЮЧ или, по крайней мере, УНИКАЛЬНЫЙ общий индекс для столбца NOT NULL.

Требования

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

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

Установка

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

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

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

$ psql -c "CREATE EXTENSION pg_repack" -d your_database

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

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

Синтаксис

pg_repack [OPTION]... [DBNAME]

Параметры

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

-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 потратит попытку подключения, обнаружив, что серверу нужен пароль. В некоторых случаях стоит ввести -W, чтобы избежать лишних попыток соединения.

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

-e, --echo

Эхо-команды, отправленные на сервер.

-E уровень, --elevel=уровень

Выбрать уровень выходного сообщения: DEBUG, INFO, NOTICE, WARNING, ERROR, LOG, FATAL и PANIC . По умолчанию INFO.

--help

Показать примеры использования программы.

--version

Показать номер версии программы.

Среда

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

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

ERROR: pg_repack VER is not installed in the database

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

ERROR: program 'pg_repack V1' does not match database library 'pg_repack V2'

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

ERROR: extension 'pg_repack V1' required, found 'pg_repack V2'

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

ERROR: relation "table" must have a primary key or not-null unique keys

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

ERROR: query failed: ERROR: column "col" does not exist

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

WARNING: the table "tbl" already has a trigger called repack_trigger

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

ERROR: Another pg_repack command may be running on the table. Please try again later.

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

WARNING: Cannot create index "schema"."index_xxxx", already exists

ПОДРОБНЕЕ: Неверный индекс мог быть оставлен предыдущим сеансом pg_repack для таблицы, которая была прервана. Используйте DROP INDEX "schema"."index_xxxxx", чтобы удалить этот индекс, и повторите попытку.

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

Ограничения

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

Временные таблицы

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

GiST-индексы

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

DDL-команды

Вы не сможете выполнять команды DDL для целевых таблиц, кроме VACUUM или ANALYZE, пока работает pg_repack. 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. сбрасывает старые индексы.

Одновременное создание индексов связано с несколькими оговорками, подробности см. в разделе Неблокирующее построение индексов.

См. также