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- це індекс кортежу, який зберігається як неподписаний 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: Я додав розділ для оновленого питання.
Erwin Brandstetter

Дякую за вичерпну відповідь. Насправді я думав, що я можу розмістити мертві рядки в кінці сторінок db за допомогою фальшивих оновлень, тобто update table set field_1 = field_1, але вакуумування цієї таблиці після цієї операції не змогла повернути вільний простір, будь-які ідеї?
неправильно про все

@Zadadlo: Ідеї, які у мене були, вже є у відповіді. :) Я не знаю про інструмент, який може змінити порядок мертвих кортежів, не потребуючи значного простору на диску. (Це не означає, що там не може бути жодного.)
Ервін Брандстеттер

Кажуть, цей інструмент робить трюк, але ще не пробували його: code.google.com/p/pgtoolkit/source/browse/trunk/bin/…
неправильно про все
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.