VACUUM возвращает дисковое пространство операционной системе

21

VACUUMобычно не возвращает дисковое пространство операционной системе, за исключением некоторых особых случаев.
Из документов:

Стандартная форма VACUUMудаляет версии мертвых строк в таблицах и индексах и отмечает пространство, доступное для повторного использования в будущем. Однако он не вернет пространство операционной системе, за исключением особого случая, когда одна или несколько страниц в конце таблицы становятся полностью свободными, и можно легко получить эксклюзивную блокировку таблицы. Напротив, VACUUM FULLактивно сжимает таблицы, записывая полную новую версию файла таблицы без мертвого пространства. Это минимизирует размер таблицы, но может занять много времени. Также требуется дополнительное дисковое пространство для новой копии таблицы, пока операция не завершится.

Вопрос в том, как эта база данных one or more pages at the end of a table become entirely freeможет определить, когда она будет достигнута. Это можно сделать с помощью VACUUM FULL, но у меня недостаточно места для его реализации. Так есть ли другие возможности?

неправильно-о-все
источник

Ответы:

29

Чтобы вернуть место в ОС, используйте 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освободить место на диске от раздутых индексов?

Что бы ты ни делал, не будь опрометчивым . Если сомневаетесь, сначала сделайте резервную копию всего в безопасном месте.

Эрвин Брандштеттер
источник
Эрвин, извини, я забыл упомянуть, что мне не хватает места для полного вакуума. Обновил вопрос.
неправильно обо всем
@Zapadlo: я добавил главу для обновленного вопроса.
Эрвин Брандштеттер
Спасибо за исчерпывающий ответ. На самом деле я думал, что я могу поместить мертвые строки в конце страниц базы данных путем фальшивых обновлений, то есть update table set field_1 = field_1, но очистка этой таблицы после этой операции не смогла вернуть свободное место, есть идеи?
неправильно обо всем
@Zapadlo: идеи, которые у меня были, уже есть в ответе. :) Я не знаю инструмента, который может переупорядочивать мертвые кортежи, не требуя значительного места для маневра на диске. (Это не значит, что там не может быть никого.)
Эрвин Брандштеттер
Говорят, этот инструмент помогает, но еще не пробовал: code.google.com/p/pgtoolkit/source/browse/trunk/bin/…
неправильно все