Чтобы вернуть место в ОС, используйте 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
- это индекс кортежа, хранящийся как unsigned 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
освободить место на диске от раздутых индексов?
Что бы ты ни делал, не будь опрометчивым . Если сомневаетесь, сначала сделайте резервную копию всего в безопасном месте.