Comments 11
pg_repack maintainer и автор патчей для поддержки всех версий postgresql начиная с 11.
Следит за всеми изменениями в оригинальной таблице (использует триггеры и лог WAL).
WAL мы не используем для отслеживания изменений
Создает временную «чистую» таблицу‑копию и индексы.
Копирует в нее все актуальные данные.
корректности ради: сначала создаём таблицу, потом пишем в неё копию данных из таблицы-источника, только потом создаём новые индексы
Блокировка все еще нужна, но только на пятом шаге и длится миллисекунды.
блокировку мы вынуждены брать дважды: в самом начале, т.к. create trigger требует аналогично блокировку, и в конце для подмены relfilenode на новые.
Миллисекунды блокировки только если никто не мешает (к таблице только быстрые запросы и их можно раздвинуть безболезненно), а вот если к табличке ещё постоянным фоном транзакции по несколько минут - остановите эту активность на время репака либо не ставьте опцию no-kill-backend чтобы репак прибил те транзакции которые мешают взять блокировку.
SELECT repack.repack_table('bloated');
это некорректный способ запуска pg_repack. Если это локальный патч вашего форка - упомяните это, пожалуйста, явно.
по vacuum (не full) - почему в табличке отмечено "Даунтайм для приложения" "да"?
ну и есть у вакуума одна особенность: он действительно может уменьшить таблицу. Но только хвост датафайлов. То есть от конца таблицы до самого дальнего тапла который не был удалён и вычищен. И зная это, если ещё вариант сжатия таблиц: https://github.com/dataegret/pgcompacttable/blob/master/bin/pgcompacttable
переместить оставшиеся живые таплы из конца таблицы, затем обычный vacuum действительно вернёт место ОС. Это особо полезно, когда нет троекратного запаса по месту на дисках (на новую копию данных, индексы, и всё это записать в WAL)
Забыли сказать самое главное про pg_repack - он требует место на диске, причем как правило x3 (место для новой таблицы равное исходной + переливка данных и потом накат изменений нагенерируют кучу WAL'оф).
Для примера я репачил таблицу размером 150GB, на диске было 50GB свободного места, в итоге в облачное DBaaS пришлось увеличить диск на 350GB и это прям впритык. А в оканцове таблица стала 140GB и что мы имеем? Мы стали больше платить за диск, тк ресайз вниз у многих облачных провайдеров не поддерживается.
Так что выводы делайте сами, а стоит ли оно того, платить больше ради копеечной выгоды.
Спасибо большое за ваш комментарий, но я явно отразил этот момент с диском в разделе "Ограничения и Грабли".
Ну и вы абсолютно правы - магии не бывает. Разные инстурменты работают с разными нюансами и ограничениями. Нужно правильно выбирать их под свои задачи.
в статье про repack https://habr.com/ru/articles/499444/ описывалась проблема с ограниченями целостности с отложенной проверкой. Не знаете ли, эта проблема до сих пор есть?
Насколько я знаю проблема с ограничениями целостности с отложенной проверкой в pgrepack всё ещё актуальна, и её нужно учитывать. Это обсуждалось и в официальном трекере pg_repack и не закрыто как решённое. Проблема затрагивает достаточно специфичные сценарии, но может быть критичной. Можно также рассмотреть pg_squeeze как альтернативу, хотя он тоже не всегда корректно работает с отоложенными проверками.
А что при этом произойдёт с foreign keys и views, которые ссылаются на оптимизируемую таблицу? А если на эту таблицу триггеры уже навешаны? Что с партицированием?
И ещё стоит не забывать про заморозку картежей, копируя данные в новую таблицу мы по факту обнуляем заморозку.
Спасибо за инетрес к статье!
Если говорить про foreign keys и views, чаще всего всё будет работать, но лучше перед использованием проверить зависимости (чтото типа SELECT * FROM pg_depend WHERE refobjid = 'your_table'::regclass;)
Триггеры переносятся, но я бы рекомендовал проверить их после репака.
Насчет шардирвоания. Увы я не эксперт. Прошу прощения, не подскажу.
В https://github.com/reorg/pg_repack/issues довольно много интересного , и про партиции и про ключи и про триггеры найдется. Я думаю даже авторы не всегда знают как оно отработает) Имхо - репак совсем не enterprise ready, если со средним объемами еще можно справиться, то с более менее большими и нагруженными данными с чуть большей сложностью схемы , чем простые plain tables + индексы - уже все совсем не весело.
Тот же pg_squeeze гораздо лучше, так как позволяет из коробки потоянный процессинг работы с bloat насторить, что в принципе более правильный подход. А pg_repack , ну такое, больше похож на костыль для тушения пожаров, а раз у тебя пожар, значит, ты уже прошляпил.
И еще по моему опыту - если вам нужен регулярно VACUUM FULL, что то у вас с моделью данных не так, где то партиционирование забыли , time-series не используют где можно и нужно итд итп.
ничего не произойдёт ни с FK, ни с триггерами, ни с ссылающимися на таблицу чем бы то ни было ещё. Фактически объявление таблицы мы вообще не трогаем, только подменяем relfilenode новым. Это довольно просто и надёжно (в том числе для новых фич), но зато делает невозможным реализацию каких-нибудь на первый взгляд уместных дополнительных возможностей: изменение типа данных колонки, например, или переупорядочивание колонок в таблице.
партицирование умеем. Я рекомендую запускать непосредственно на каждую индивидуальную партицию чем через голову.
visibility map сбросится как побочный эффект, да. Если активно используется index only scan для запроса - ему поплохеет.
Раздувание таблиц в PostgreSQL: работа с vacuum и pg_repack