Щоб повернути простір в ОС, використовуйте VACUUM FULL
. Будучи на ній, я гадаю, ти біжиш VACUUM FULL ANALYZE
. Я цитую посібник :
FULL
Вибирає "повний" вакуум, який може забирати більше місця , але займає набагато більше часу і виключно блокує стіл. Цей метод також вимагає додаткового місця на диску, оскільки він записує нову копію таблиці і не випускає стару копію до завершення операції. Зазвичай це слід використовувати лише тоді, коли значну кількість місця потрібно забирати зсередини таблиці.
Сміливий акцент мій.
CLUSTER
досягає цього також як побічний ефект.
Звичайний VACUUM
звичайно не досягає вашої мети ( "одна або кілька сторінок у кінці таблиці повністю безкоштовні" ). Він не впорядковує рядки і лише обрізає порожні сторінки з фізичного кінця файлу, коли з'являється можливість - як ваша цитата з інструкцій з посібника.
Ви можете отримати порожні сторінки в кінці фізичного файлу, коли ви будете додавати INSERT
партію рядків і DELETE
їх до того, як будуть додані інші кортежі. Або це може статися за збігом обставин, якщо буде видалено достатньо рядків.
Існують також спеціальні налаштування, які можуть запобігти VACUUM FULL
поверненню місця. Побачити:
Підготуйте порожні сторінки в кінці таблиці для тестування
Системний стовпчик ctid
представляє фізичне положення рядка. Вам потрібно зрозуміти цей стовпець:
Ми можемо працювати з цим і підготувати таблицю, видаливши всі рядки з останньої сторінки:
DELETE FROM tbl t
USING (
SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid AS min_tid
, (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
FROM tbl
ORDER BY ctid DESC
LIMIT 1
) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;
Тепер остання сторінка порожня. Це ігнорує паралельні записи. Або ви єдиний, хто пише в цю таблицю, або вам потрібно зробити блокування запису, щоб уникнути перешкод.
Запит оптимізовано для швидкого виявлення кваліфікованих рядків. Друге число a tid
- це індекс кортежу, який зберігається як неподписаний int2
, і 65535
є максимальним для цього типу ( 2^16 - 1
), тому це безпечна верхня межа.
SQL Fiddle (повторне використання простої таблиці з іншого випадку.)
Інструменти для вимірювання розміру рядків / таблиць:
Диск повний
Для будь-якої з цих операцій вам потрібна мерехтіння на диску. Також є засіб спільноти pg_repack
як заміна для VACUUM FULL
/ CLUSTER
. Він уникає ексклюзивних замків, але також потребує вільного місця для роботи. Посібник:
Потрібно вільне місце на диску вдвічі більше, ніж цільова таблиця (таблиці) та індекси.
В крайньому випадку, ви можете запустити цикл скидання / відновлення. Це також видаляє все набряк із таблиць та індексів. Питання, що пов'язані між собою:
Відповідь там досить радикальна. Якщо ваша ситуація це дозволяє (відсутність сторонніх ключів чи інших посилань, що перешкоджають видаленню рядків), і немає одночасного доступу до таблиці), ви можете просто:
Завантажте таблицю на диск, який з'єднується з віддаленого комп'ютера з великою кількістю дискового простору ( -a
для --data-only
):
З віддаленої оболонки дані дамп-таблиці:
pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql
У сесії pg TRUNCATE
таблиця:
-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;
Віддалену оболонку відновіть до тієї ж таблиці:
psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here
Зараз він не містить жодних мертвих рядів або набряків.
Але, може, ти можеш так просто?
Чи можете ви зробити достатньо місця на диску, видаливши (перемістивши) непов'язані файли?
Чи можете ви VACUUM FULL
спочатку зменшити таблиці по черзі, звільнивши достатньо місця на диску?
Чи можете ви запустити REINDEX TABLE
чи REINDEX INDEX
звільнити місце на диску від роздутих індексів?
Що б ви не робили, не будьте необдумані . Якщо ви сумніваєтеся, спершу створіть резервну копію всього в безпечному місці.