Мне нужно запустить VACUUM FULL без свободного места на диске

27

У меня есть одна таблица, которая занимает около 90% дискового пространства на нашем сервере. Я решил оставить несколько столбцов, чтобы освободить место. Но мне нужно вернуть место под ОС. Проблема, однако, в том, что я не уверен, что произойдет, если я запусту VACUUM FULL и не хватит свободного места, чтобы сделать копию таблицы.

Я понимаю, что VACUUM FULL не следует использовать, но я решил, что это лучший вариант в этом сценарии.

Любые идеи поощряются.

Я использую PostgreSQL 9.0.6

Джастин
источник

Ответы:

19

Поскольку у вас недостаточно места для запуска vacumm или восстановления, вы всегда можете восстановить свои базы данных postgresql, восстановив их. Восстановление баз данных, таблиц, индексов освободит место и дефрагментирует. После этого вы можете настроить автоматическое обслуживание, чтобы регулярно пылесосить ваши базы данных.

1 Сделайте резервную копию всех баз данных на вашем сервере postgresql

Вы хотите сделать резервную копию всех ваших баз данных в раздел, который имеет достаточно места. Если вы работали в Linux, вы можете использовать gzip для дальнейшего сжатия резервной копии для экономии места

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2 Сделайте резервную копию ваших файлов конфигурации

cp /path/to/postgresql/data_directory/*.conf /some/partition/

3 Стоп Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop

4 стереть содержимое каталога данных

rm -Rf /path/to/postgresql/data_directory/*

5 Запустите initdb, чтобы восстановить вашу директорию данных

initdb -D /path/to/postgresql/data_directory

6 Восстановите файлы конфигурации

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7 Запустите Postgresql

pg_ctl -D /path/to/postgresql/data_directory start

8 Восстановите дамп всех созданных вами баз данных.

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out
Крейг Эфрейн
источник
1
Спасибо, это то, что я закончил, с несколькими отличиями. Я просто сбросил базу данных после ее резервного копирования. Затем создал новый и восстановил его.
Джастин
Пожалуйста. Я подумал, что удаления содержимого каталога данных и выполнения initdb было бы достаточно, хотя.
Крейг Эфрейн
Работал отлично, я просто рекомендую пропустить gzipчасть, чтобы сэкономить время.
Рафаэль Барбоса
17

ПРИМЕЧАНИЕ. Я проверил это на 9.1. У меня нет сервера 9.0 валяется здесь. Я уверен, что он будет работать на 9.0, хотя.


ВНИМАНИЕ (как отмечено в комментариях @erny):

Note that high CPU load due to I/O operations may be expected.

Вы можете сделать это практически без простоев, используя временное табличное пространство. Простои будут в виде эксклюзивных замков. Но только на столе вы пылесосите. Таким образом, все, что произойдет, - это то, что клиентские запросы будут просто ждать получения блокировки, если они получат доступ к рассматриваемой таблице. Вам не нужно закрывать существующие соединения.

Однако следует помнить, что для перемещения стола и полного вакуума в первую очередь потребуется подождать эксклюзивной блокировки!


Во-первых, вам, очевидно, нужно дополнительное хранилище. Как Stéphaneупоминается в комментариях, это должно быть как минимум вдвое больше, чем рассматриваемая таблица, как VACUUM FULLи полная копия. Если вам повезло, и вы можете динамически добавить диск к машине, сделайте это. В худшем случае вы можете просто подключить USB-диск (хотя и рискованно и медленно)!

Далее, смонтируйте новое устройство и сделайте его доступным как табличное пространство:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

Вы можете легко перечислить табличные пространства, используя:

\db

Дважды проверьте текущее табличное пространство вашей таблицы (вам нужно знать, куда ее перенести):

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

Если это так NULL, он будет в табличном пространстве по умолчанию:

SHOW default_tablespace;

Если что это NULLтак, то, вероятно , будет pg_default(проверьте официальные документы в случае , если он изменен).

Теперь переместите стол:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

Вакуум это:

VACUUM FULL mytable;

Переместите это назад:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off

Удалить временное пространство:

DROP TABLESPACE tempspace;
exhuma
источник
NB. Похоже, что ход использует больше места на диске в исходном каталоге данных ...
Крис Уизерс,
Только что проверил на 9.3, и он работает как шарм.
Бартек Яблонски
Успешно используется в производстве на 9.1. После изменения табличного пространства исходное используемое пространство освобождается. Обратите внимание, что может ожидаться высокая загрузка процессора из-за операций ввода-вывода.
Эрни
2
Удивительные советы, спасибо за это подробное объяснение. Обратите внимание, что во временном табличном пространстве вам потребуется, по крайней мере size of table x 2, поскольку VACUUM FULLсоздается полная копия таблицы.
Стефан
Спасибо, Стефан. Я добавил информацию в основной корпус.
exhuma
2

Быстро и грязно:

  • Стоп Постгрес
  • Переместите основной каталог базы данных на другой диск, где достаточно места для очистки
  • В исходном местоположении main добавьте символическую ссылку на новое местоположение
  • вакуум
  • Удалите символическую ссылку и переместите основной каталог обратно в исходное местоположение.
  • Начать Postgres

Например,:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start

Роджер Даль
источник
0

Если у вас есть место на диске для выполнения дампа и восстановления, у вас должно быть место на диске для создания вакуума db --full. Проблема в том, что вакуумный файл db --full сделает копию всего файла данных. Итак, что вы могли бы сделать:

  1. скопируйте файлы, которые содержат огромную таблицу, на другой диск, например, на медленный, больший диск.
  2. сделать символические ссылки из исходного места на новое место на другом диске.
  3. запустите вакуумный диск --full, теперь он должен прочитать данные с другого диска и записать окончательную таблицу на исходный диск с данными.
Гюнтер
источник