pg_repack
pg_repack — утилита и расширение QHB для реорганизации таблиц
Синтаксис
pg_repack [параметр...] [имя_бд]
Описание
pg_repack — это расширение QHB, которое позволяет
избавляться от «разбухания» таблиц и индексов и при необходимости восстанавливать
физический порядок кластеризованных индексов. В отличие от команд CLUSTER и
VACUUM FULL, оно делает это в реальном времени, не удерживая
эксклюзивную блокировку таблиц во время их обработки. Кроме того, pg_repack
очень эффективно, его производительность сравнима с прямым использованием CLUSTER.
Для реорганизации таблиц можно выбрать один из следующих способов:
- Выполнение в режиме реального времени команды
CLUSTER(упорядочивание по кластерному индексу); - Упорядочивание по указанным столбцам;
- Выполнение в режиме реального времени команды
VACUUM FULL(упаковка только строк); - Перестройка или перемещение только индексов таблицы.
Примечание
Использовать эту утилиту могут только суперпользователи либо владельцы таблиц и индексов. Чтобы выполнить pg_repack от имени такого владельца, нужно воспользоваться параметром --no-superuser-check.
Примечание
Целевая таблица должна иметь первичный ключ (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
Не перепаковывать таблицы, принадлежащие конкретному расширению. Некоторые
расширения могут сильно зависеть от таких таблиц во время планирования и т. д.
--no-error-on-invalid-index
Провести перепаковку, даже если найден нерабочий индекс.
--error-on-invalid-index
Не проводить перепаковку, если найден нерабочий индекс (считается устаревшим,
поскольку теперь это поведение по умолчанию).
--apply-count=число_кортежей
Количество кортежей, которые будут применяться в одной транзакции при воспроизведении.
--switch-threshold=число_кортежей
Переставить таблицы, когда в таблице журнала осталось это количество кортежей.
Этот параметр можно использовать во избежание трудностей с наверстыванием таблиц
с интенсивной записью данных.
Параметры подключения
Параметры для подключения к серверам. Параметры -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 для таблицы, которая была прервана и по какой-то причине не смогла удалить временные объекты.
Удалить все временные объекты можно, удалив и заново создав расширение: подробную информацию см. в параграфе Установка.
WARNING: trigger "trg" conflicting on table "tbl"
-- ПРЕДУПРЕЖДЕНИЕ: триггер "trg" конфликтует с таблицей "tbl"
У целевой таблицы имеется триггер, имя которого идет за z_repack_trigger в алфавитном порядке.
z_repack_trigger должен быть последним срабатывающим триггером BEFORE. Переименуйте свой триггер, чтобы по алфавиту он шел перед триггером pg_repack; для этого можно выполнить:
ALTER TRIGGER zzz_my_trigger
ON sometable RENAME TO yyy_my_trigger;
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:
- создает таблицу журнала для записи изменений, внесенных в исходную таблицу;
- добавляет триггер в исходную таблицу для регистрации команд
INSERT,UPDATEиDELETEв таблице журнала; - создает новую таблицу, содержащую все строки из старой таблицы;
- строит индексы в этой новой таблице;
- применяет все изменения, которые произошли в таблице журнала, к новой таблице;
- переставляет таблицы, включая индексы и таблицы TOAST, используя системные каталоги;
- удаляет исходную таблицу.
pg_repack будет удерживать блокировку ACCESS EXCLUSIVE только в
течение короткого периода времени во время первоначальной настройки (шаги 1 и 2)
и на заключительном этапе перестановки и удаления (шаги 6 и 7). В остальное время
pg_repack нужно удерживать только блокировку ACCESS SHARE для исходной
таблицы, что означает, что операции INSERT, UPDATE и DELETE могут выполняться
как обычно.
Перепаковка только индексов
Чтобы выполнить перепаковку только для индекса, pg_repack проводит следующие операции:
- создает новые индексы в таблице, используя неблокирующее (CONCURRENTLY) сопоставление определений старых индексов;
- заменяет в каталогах старые индексы на новые;
- удаляет старые индексы.
Неблокирующее создание индексов осуществляется с несколькими оговорками; подробную
информацию см. в параграфе Неблокирующее построение индексов на справочной
странице команды CREATE INDEX.