Vacuuming
Обзор
ADPG/PostgreSQL поддерживает согласованность данных с помощью мультиверсионной модели (Multiversion Concurrency Control, MVCC). Используется система управления версиями кортежа (tuple) — данные не изменяются и не удаляются во время обработки транзакций, а в таблицу добавляется новая версия записи. Эта запись называется кортежем (tuple). Кортежи, удаленные или устаревшие в результате обновления, физически не удаляются из таблиц, а помечаются с помощью специальных полей. Строка в таблице, помеченная для удаления, но еще не удаленная физически, называется мертвым кортежем (dead tuple). Операция вакуумирования (vacuuming) освобождает память, занятую мертвыми кортежами.
Регулярно выполнять вакуумирование каждой таблицы необходимо по нескольким причинам:
-
для высвобождения или повторного использования дискового пространства, занятого измененными или удаленными строками;
-
для обновления статистики данных, используемой планировщиком запросов;
-
для обновления карты видимости, которая ускоряет index-only scans;
-
для защиты от потери очень старых данных из-за переноса (wraparound) идентификатора транзакции или переноса (wraparound) идентификатора мультитранзакции.
Различные причины требуют, чтобы вакуумирование выполнялось с разной частотой и в разной степени, как обсуждается в подразделах ниже.
В большинстве случаев предпочтительно, чтобы вакуумирование выполнялась с помощью демона autovacuum, который автоматизирует выполнение команды VACUUM
.
Команды VACUUM и VACUUM FULL
Как упоминалось выше, кортежи, удаленные или устаревшие в результате обновления, физически не удаляются из таблиц. Каждый кортеж содержит служебную информацию — HeapTupleHeaderData, которая позволяет определить, является ли текущий кортеж актуальной версией строки или он устарел. (За дополнительной информацией о структуре HeapTupleHeaderData обратитесь к разделу Table row layout.)
Создайте и заполните таблицу данными для просмотра полей HeapTupleHeaderData:
CREATE TABLE test (
id serial PRIMARY KEY,
num int
);
INSERT INTO test (num) VALUES (10),(20),(30);
Удалите строку из этой таблицы и обновите другую строку:
UPDATE test SET num = 25 where id = 2;
DELETE FROM test WHERE id = 3;
Просмотрите данные таблицы, включая столбцы со служебной информацией:
SELECT id, num, xmin,xmax,cmin,cmax,ctid FROM test;
Отобразятся две строки, вторая имеет новый номер транзакции вставки:
id | num | xmin | xmax | cmin | cmax | ctid ----+-----+---------+------+------+------+------- 1 | 10 | 2339945 | 0 | 7 | 7 | (0,1) 2 | 25 | 2339949 | 0 | 0 | 0 | (0,4) (2 rows)
Были выведены следующие скрытые поля:
-
xmin
— идентификатор транзакции, создавшей запись для этой версии строки. -
xmax
— идентификатор удаляющей транзакции или ноль для неудаленной версии строки. -
cmin
— порядковый номер команды в транзакции, добавившей запись. -
cmax
— порядковый номер команды в транзакции, удалившей запись или ноль. -
ctid
— физическое расположение текущей версии строки в таблице. Для актуальной версии строкиctid
указывает на саму эту версию.ctid
имеет следующую форму:(<номер страницы>, <индекс в массиве>)
.
Чтобы просмотреть мертвые кортежи, необходимо установить расширение pageinspect:
CREATE EXTENSION pageinspect;
Запустите следующий запрос, использующий функцию heap_page_items для отображения всех кортежей:
SELECT lp as tuple, t_xmin, t_xmax, t_ctid FROM heap_page_items(get_raw_page('test',0));
Результат:
tuple | t_xmin | t_xmax | t_cid | t_ctid -------+---------+---------+-------+-------- 1 | 2339945 | 0 | 7 | (0,1) 2 | 2339945 | 2339949 | 0 | (0,4) 3 | 2339945 | 2339949 | 1 | (0,3) 4 | 2339949 | 0 | 0 | (0,4)
Таблица test
содержит два мертвых кортежа (2
и 3
).
Затем запустите команду VACUUM. Можно использовать ключевое слово VERBOSE
для печати подробного отчета о выполнении операции вакуумирования:
VACUUM VERBOSE test;
Результат:
INFO: vacuuming "public.test" INFO: scanned index "test_pkey" to remove 1 row versions DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: table "test": removed 1 dead item identifiers in 1 pages DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: index "test_pkey" now contains 2 row versions in 2 pages DETAIL: 1 index row versions were removed. 0 index pages were newly deleted. 0 index pages are currently deleted, of which 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: table "test": found 2 removable, 2 nonremovable row versions in 1 out of 1 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 2378768 Skipped 0 pages due to buffer pins, 0 frozen pages. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. VACUUM
Кроме того, каждый сервер, на котором выполняется VACUUM
без опции FULL
, будет сообщать о своем прогрессе в представлении pg_stat_progress_vacuum
.
Выполните упомянутый выше запрос, чтобы просмотреть все кортежи в таблице test
:
SELECT lp as tuple, t_xmin, t_xmax, t_ctid FROM heap_page_items(get_raw_page('test',0));
Результат:
tuple | t_xmin | t_xmax | t_ctid -------+---------+--------+------- 1 | 2339945 | 0 | (0,1) 2 | | | 3 | | | 4 | 2339949 | 0 | (0,4) (4 rows)
Из результата видно, что VACUUM
удаляет мертвые кортежи, но не освобождает дисковое пространство. Однако VACUUM
делает его доступным для повторного использования, и вместо удаленных мертвых кортежей будут записаны новые.
Вы также можете использовать запрос к представлению pg_stat_user_tables
для получения статистики по кортежам:
SELECT relname, n_live_tup, n_dead_tup
FROM pg_stat_user_tables WHERE relname = 'test';
Результат:
relname | n_live_tup | n_dead_tup ---------+------------+------------ test | 2 | 2
Если таблицы и столбцы не указаны в команде VACUUM
, она обрабатывает каждую таблицу и материализованное представление в текущей базе данных. Также VACUUM
не может быть выполнен внутри блока транзакции.
VACUUM
генерирует значительный объем трафика ввода-вывода, что может привести к снижению производительности других активных сесий. PostgreSQL предоставляет параметры конфигурации, которые можно настроить, чтобы снизить влияние фонового вакуумирования на производительность — см. Cost-based vacuum delay. Используйте специальный раздел postgresql.conf для установки параметров вакуумирования, как описано в Конфигурационные параметры.
Можно получить текущие настройки вакуумирования из представления pg_settings, используя следующий запрос:
SELECT name, setting, context, short_desc
FROM pg_settings WHERE name like 'vacuum%';
Результат:
name | setting | context | short_desc -----------------------------------+------------+---------+------------------------------------------------------------------------------------- vacuum_cost_delay | 0 | user | Vacuum cost delay in milliseconds. vacuum_cost_limit | 200 | user | Vacuum cost amount available before napping. vacuum_cost_page_dirty | 20 | user | Vacuum cost for a page dirtied by vacuum. vacuum_cost_page_hit | 1 | user | Vacuum cost for a page found in the buffer cache. vacuum_cost_page_miss | 2 | user | Vacuum cost for a page not found in the buffer cache. vacuum_defer_cleanup_age | 0 | sighup | Number of transactions by which VACUUM and HOT cleanup should be deferred, if any. vacuum_failsafe_age | 1600000000 | user | Age at which VACUUM should trigger failsafe to avoid a wraparound outage. vacuum_freeze_min_age | 50000000 | user | Minimum age at which VACUUM should freeze a table row. vacuum_freeze_table_age | 150000000 | user | Age at which VACUUM should scan whole table to freeze tuples. vacuum_multixact_failsafe_age | 1600000000 | user | Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage. vacuum_multixact_freeze_min_age | 5000000 | user | Minimum age at which VACUUM should freeze a MultiXactId in a table row. vacuum_multixact_freeze_table_age | 150000000 | user | Multixact age at which VACUUM should scan whole table to freeze tuples.
Существует два варианта команды VACUUM
: стандартный VACUUM
и VACUUM FULL
. VACUUM FULL
может освободить больше дискового пространства, но работает гораздо медленнее. Кроме того, стандартная форма VACUUM
может выполняться параллельно с операциями в производственной базе данных. Команды SELECT
, INSERT
, UPDATE
и DELETE
продолжат работать нормально, хотя невозможно будет изменить определение таблицы с помощью таких команд, как ALTER TABLE
, пока работает VACUUM
.
Запустите VACUUM FULL
для таблицы test
:
VACUUM FULL test;
Выполните упомянутый выше запрос, чтобы просмотреть все кортежи в таблице test
:
SELECT lp as tuple, t_xmin, t_xmax, t_ctid FROM heap_page_items(get_raw_page('test',0));
В выводе видно, что пустые строки были удалены:
tuple | t_xmin | t_xmax | t_ctid -------+---------+--------+-------- 1 | 2339945 | 0 | (0,1) 2 | 2339949 | 0 | (0,2)
VACUUM FULL
создает новую копию таблицы и освобождает дисковое пространство. VACUUM FULL
требует блокировки ACCESS EXCLUSIVE
для таблицы и не может выполняться параллельно с другими операциями. VACUUM FULL
может освободить больше места, но это занимает гораздо больше времени. Этот метод также требует дополнительного дискового пространства, поскольку он записывает новую копию таблицы и не освобождает старую копию до завершения операции. Как правило, VACUUM FULL
следует использовать только тогда, когда необходимо освободить значительный объем пространства. Администраторам следует стремиться использовать стандартный VACUUM
и избегать VACUUM FULL
.
РЕКОМЕНДАЦИЯ
Вы можете использовать запрос к представлению
Результат: relname | n_live_tup | n_dead_tup ---------+------------+------------ test | 2 | 3 |
Освобождение дискового пространства
Как упоминалось выше, команды UPDATE
и DELETE
не удаляют сразу старую версию строки. Этот подход необходим для получения преимуществ управления многоверсионным параллелизмом: версию строки нельзя удалять, пока она потенциально видна другим транзакциям. Со временем устаревшая или удаленная версия строки перестает представлять интерес для какой-либо транзакции. Занимаемое ей пространство должно быть освобождено для повторного использования новыми строками, чтобы избежать неограниченного роста занятого дискового пространства. Как подробно рассматривалось выше, стандартная форма VACUUM
удаляет версии мертвых строк в таблицах и индексах и отмечает пространство, доступное для будущего повторного использования. Однако VACUUM
не возвращает пространство операционной системе, за исключением особого случая, когда одна или несколько страниц в конце таблицы становятся полностью свободными и можно легко получить эксклюзивную блокировку таблицы. В то время как VACUUM FULL
записывает новую версию файла таблицы без мертвого пространства. Это минимизирует размер таблицы, но может занять много времени и требует дополнительного дискового пространства.
Обычно целью регулярного вакуумирования является выполнение стандартной команды VACUUM
достаточно часто, чтобы избежать необходимости выполнять VACUUM FULL
. Основная идея этого подхода — не минимизировать размер таблиц, а поддерживать использование дискового пространства на стабильном уровне: каждая таблица занимает пространство, равное её минимальному размеру плюс пространство, используемое между операциями вакуумирования. Хотя вы можете использовать VACUUM FULL
, чтобы сжать таблицу до минимума и вернуть дисковое пространство операционной системе, в этом нет особого смысла, если в будущем таблица снова вырастет. Для часто обновляемых таблиц лучше запускать VACUUM
с умеренной частотой, чем очень редко запускать VACUUM FULL
.
РЕКОМЕНДАЦИЯ
|
Обновление статистики планировщика
Планировщик запросов полагается на статистическую информацию о содержимом таблиц для создания качественных планов запросов. Эта статистика собирается командой ANALYZE, которую можно вызвать отдельно или как дополнительный шаг при выполнении VACUUM
. Важно иметь точную статистику, так как неправильно выбранные планы запросов могут снизить производительность базы данных.
Демон autovacuum запускает команду ANALYZE
всякий раз, когда содержимое таблицы существенно изменилось. Однако администраторы могут предпочесть выполнить ANALYZE
вручную, так как демон планирует запуск ANALYZE
строго в зависимости от количества вставленных или обновленных строк. Демон не имеет информации, приведут ли эти изменения к значимому изменению статистики.
Изменения в секциях секционированных таблиц и в дочерних таблицах не вызывают команду ANALYZE
для родительской таблицы. Если родительская таблица пуста или редко изменяется, она может никогда не обрабатываться autovacuum и статистика для дерева наследования не будет собрана. Необходимо вручную запускать ANALYZE
для родительских таблиц, чтобы поддерживать актуальность статистики.
Обновление карты видимости
Вакуумирование поддерживает карту видимости для каждой таблицы, чтобы отслеживать, какие страницы содержат только кортежи, видимые всем активным транзакциям (и всем будущим транзакциям, пока страница не будет изменена). Это преследует две цели. Во-первых, вакуумирование может пропустить такие страницы при следующем запуске, так как очищать нечего. Во-вторых, это позволяет ADPG/PostgreSQL выполнять некоторые запросы, используя только индекс, без ссылки на базовую таблицу. Поскольку индексы не содержат информации о видимости кортежа, стандартное сканирование индекса извлекает кортеж для каждой соответствующей записи индекса, чтобы проверить, может ли он быть просмотрен текущей транзакцией. При сканировании index-only scan сначала проверяется карта видимости. Если все кортежи на странице видны, то выборку для проверки видимости можно пропустить. Это наиболее полезно для больших наборов данных, где карта видимости может предотвратить доступ к диску.
Предотвращение сбоев переноса (wraparound) идентификаторов транзакций
Семантика транзакций PostgreSQL MVCC зависит от возможности сравнения номеров идентификаторов транзакций (XID): версия строки с XID, превышающим XID текущей транзакции, находится "в будущем" и не должна быть видна для текущей транзакции. Поскольку идентификаторы транзакций имеют ограниченный размер (32 бита), кластер, работающий в течение длительного времени (более 4 миллиардов транзакций), будет подвергаться циклическому переносу номеров (wraparound) идентификаторов транзакций. Когда счетчик XID обнуляется, транзакции, которые были "в прошлом", окажутся "в будущем". Это означает, что их вывод станет невидимым, что приведет к потере данных. На самом деле данные все еще есть, но вы не можете их получить. Чтобы этого избежать, необходимо выполнять вакуумирование всех таблиц во всех базах данных не реже одного раза каждые два миллиарда транзакций.
Периодическое вакуумирование решает проблему. VACUUM
помечает строки как замороженные (frozen), указывая, что они вставлены транзакцией, которая была зафиксирована достаточно давно в прошлом и должна быть видна всем текущим и будущим транзакциям.
В PostgreSQL выделено 32 бита для XID (около 4 миллиардов значений). Это означает, что на каждую транзакцию приходится два миллиарда "старых" XID и два миллиарда "более новых". Пространство XID идет по кругу и не имеет конечной точки. Таким образом, как только версия строки будет создана с определенным XID, она будет отображаться "в прошлом" для следующих двух миллиардов транзакций. Если версия строки все еще существует после более чем двух миллиардов транзакций, она внезапно окажется "в будущем". Чтобы это предотвратить, PostgreSQL резервирует специальный XID — FrozenTransactionId
, который не соответствует обычным правилам сравнения XID и всегда считается старше любого обычного XID. Замороженные версии строк находятся "в прошлом" для всех обычных транзакций, поэтому такие версии строк будут действительны до тех пор, пока не будут удалены, независимо от того, как долго это длится.
Параметр vacuum_freeze_min_age определяет возраст отсечения транзакций, который VACUUM
должен использовать, чтобы решить, следует ли замораживать версии строк (используйте раздел ADPG configurations, чтобы его установить, см. Конфигурационные параметры). Увеличение этого параметра позволяет избежать ненужной работы, если строки, которые могли быть заморожены, вскоре будут снова изменены. Уменьшение этого параметра увеличивает количество транзакций, которые могут выполниться прежде чем потребуется очередное вакуумирование таблицы.
VACUUM
использует карту видимости, чтобы определить, какие страницы таблицы необходимо сканировать. Обычно он пропускает страницы, у которых нет версий мертвых строк, даже если на этих страницах все еще есть версии строк со старыми значениями XID. Поэтому VACUUM
не всегда замораживает каждую старую версию строки в таблице. Периодически VACUUM
выполняет агрессивное вакуумирование, пропуская только страницы, которые не содержат ни мертвых строк, ни незамороженных значений XID или MXID. Параметр vacuum_freeze_table_age управляет тем, когда VACUUM
делает это. Все видимые, но не все замороженные страницы сканируются, если количество транзакций, прошедших с момента последнего такого сканирования, больше, чем vacuum_freeze_table_age
минус vacuum_freeze_min_age
. Установка для vacuum_freeze_table_age
значения 0
заставляет VACUUM
использовать эту более агрессивную стратегию для всех сканирований.
Максимальное время, в течение которого таблица может не очищаться, составляет два миллиарда транзакций минус значение vacuum_freeze_min_age
на момент последнего агрессивного вакуумирования. Если таблица не очищается дольше, возможна потеря данных. Чтобы этого не произошло, автовакуум вызывается для любой таблицы, которая может содержать незамороженные строки с XID старше возраста, указанного в параметре autovacuum_freeze_max_age
. Это происходит, даже если демон autovacuum отключен.
Чтобы отслеживать возраст самых старых незамороженных XID в базе данных, VACUUM сохраняет статистику XID в системных таблицах pg_class и pg_database. В частности, столбец relfrozenxid
в pg_class
содержит XID отсечки замораживания, который использовался последним агрессивным вакуумированием для текущей таблицы. Все строки, вставленные транзакциями с XID старше этого предельного XID, гарантированно замораживаются. Аналогично, столбец datfrozenxid
pg_database
содержит нижнюю границу обычных значений XID, встречающихся в текущей базе данных — это минимальное из всех значение relfrozenxid
для таблиц в базе данных. Удобный способ просмотреть эту информацию — выполнить приведенные ниже запросы. В их результатах столбец age
содержит количество транзакций от предельного XID до XID текущей транзакции.
Запрос к pg_class
:
SELECT c.oid::regclass as table_name,
greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age
FROM pg_class c
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm');
Результат:
table_name | age --------------------------------------------+--------- books_log | 649725 books | 650456 book_orders | 929364 accounts | 486357 pg_statistic | 2300534 pg_type | 2300534 employees | 447694 pg_foreign_table | 2300534 pg_authid | 2300534 pg_statistic_ext_data | 2300534 pg_user_mapping | 2300534 pg_subscription | 2300534 pg_attribute | 2300534 pg_proc | 2300534 pg_class | 2300534 pg_attrdef | 2300534 pg_constraint | 2300534 pg_inherits | 2300534 ...
Запрос к pg_database
:
SELECT datname, age(datfrozenxid) FROM pg_database;
Результат:
datname | age --------------+--------- postgres | 2300549 adpg_metrics | 2300549 template1 | 2300549 template0 | 2300549 bookstore | 2300549 adpg_db1 | 2300549 adpg_db2 | 2300549 sb_tpcc | 2300549
Если по какой-то причине автовакууму не удается удалить старые XID из таблицы, система начинает выдавать предупреждения, когда самые старые XID базы данных достигают сорока миллионов транзакций от точки переноса:
WARNING: database "mydatabase" must be vacuumed within 39985967 transactions HINT: To avoid a database shutdown, execute a database-wide VACUUM in that database.
Ручной запуск VACUUM
должен решить проблему, как подсказывает сообщение. Обратите внимание, что VACUUM
должен выполняться суперпользователем.
Если эти предупреждения игнорировать, система откажется назначать новые XID, когда до завершения цикла обработки останется менее трех миллионов транзакций. В этом состоянии любые уже выполняемые транзакции могут продолжаться, но могут быть запущены только транзакции только для чтения. Операции, изменяющие записи базы данных или удаляющие отношения, завершатся ошибкой.
Мультитранзакции и перенос идентификаторов транзакций
Multixact IDs используются для поддержки блокировки строк несколькими транзакциями. Поскольку в заголовке кортежа имеется только ограниченное пространство для хранения информации о блокировке, когда существует более одной транзакции, одновременно блокирующей строку, эта информация кодируется как идентификатор мультитранзакции (multiple transaction ID, multixact ID). Информация о том, какие идентификаторы транзакций принадлежат конкретному идентификатору мультитранзакции, хранится отдельно в подкаталоге pg_multixact
, а в поле xmax
заголовка кортежа хранится только идентификатор мультитранзакции. Как и идентификаторы транзакций, идентификаторы мультитранзакций реализованы в виде 32-битного счетчика и хранятся аналогичным образом, что требует тщательного управления их возрастом, очистки хранилища и циклической обработки.
Всякий раз, когда VACUUM
сканирует любую часть таблицы, он заменяет любой обнаруженный идентификатор мультитранзакции (поле xmax
), который старше, чем vacuum_multixact_freeze_min_age, на другое значение, которое может быть нулевым значением, идентификатором одиночной транзакции или более новым идентификатором мультитранзакции. Для каждой таблицы pg_class.relminmxid
хранит самый старый возможный идентификатор мультитранзакции из любого кортежа текущей таблицы. Если это значение старше, чем vacuum_multixact_freeze_table_age, принудительно выполняется агрессивное вакуумирование.
По соображениям безопасности агрессивное вакуумное сканирование будет выполняться для любой таблицы, возраст мультитранзакции которой превышает autovacuum_multixact_freeze_max_age. Кроме того, если объем хранилища, занимаемого членами мультитранзакций, превышает 2 ГБ, агрессивное вакуумное сканирование будет выполняться чаще для всех таблиц, начиная с таблиц, имеющих самый старый возраст мультитранзакций. Оба этих вида агрессивного сканирования будут выполняться, даже если демон autovacuum отключен.
Как и в случае с XID, если при автовакууме не удается удалить старые MXID из таблицы, система начнет выдавать предупреждающие сообщения, когда самые старые MXID базы данных достигнут сорока миллионов транзакций от точки переноса. Если эти предупреждения игнорировать, система откажется генерировать новые MXID, если до завершения обработки останется менее трех миллионов.
Autovacuum
В ADPG/PostgreSQL настоятельно рекомендуется использовать функцию автовакуума, которая автоматизирует выполнение команд VACUUM
и ANALYZE
. Если автовакуум включен, он проверяет таблицы с большим количеством вставленных, обновленных или удаленных кортежей. При этих проверках используются средства сбора статистики, поэтому автовакуум будет работать, только если для параметра track_counts
установлено значение true
(значение по умолчанию).
Демон autovacuum состоит из нескольких процессов. Существует фоновый процесс, называемый процессом запуска автовакуума (autovacuum launcher), который отвечает за запуск рабочих процессов автовакуума для всех баз данных. Процесс запуска будет распределять работу по времени, пытаясь запустить по одному рабочему процессу (worker) в каждой базе данных каждые autovacuum_naptime секунды. Если имеется N
баз данных, новый рабочий процесс запускается каждые autovacuum_naptime
/N
секунд. Параметр autovacuum_max_workers устанавливает максимальное количество рабочих процессов, которые разрешено запускать одновременно. Если необходимо обработать больше баз данных чем autovacuum_max_workers
, следующая база данных будет обработана, как только завершит работу первый рабочий процесс. Каждый рабочий процесс проверяет каждую таблицу в своей базе данных и при необходимости выполняет VACUUM
и/или ANALYZE
.
По умолчанию автовакуум включен и параметры конфигурации установлены соответствующим образом. Можно использовать следующий запрос для просмотра значений параметров автовакуума:
SELECT name, setting, context, short_desc
FROM pg_settings WHERE name like 'autovacuum%';
Результат:
name | setting | context | short_desc -------------------------------------+----------+------------+------------------------------------------------------------------------------------------- autovacuum | on | sighup | Starts the autovacuum subprocess. autovacuum_analyze_scale_factor | 0.1 | sighup | Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples. autovacuum_analyze_threshold | 50 | sighup | Minimum number of tuple inserts, updates, or deletes prior to analyze. autovacuum_freeze_max_age | 200000000| postmaster | Age at which to autovacuum a table to prevent transaction ID wraparound. autovacuum_max_workers | 3 | postmaster | Sets the maximum number of simultaneously running autovacuum worker processes. autovacuum_multixact_freeze_max_age | 400000000| postmaster | Multixact age at which to autovacuum a table to prevent multixact wraparound. autovacuum_naptime | 60 | sighup | Time to sleep between autovacuum runs. autovacuum_vacuum_cost_delay | 2 | sighup | Vacuum cost delay in milliseconds, for autovacuum. autovacuum_vacuum_cost_limit | -1 | sighup | Vacuum cost amount available before napping, for autovacuum. autovacuum_vacuum_insert_scale_factor| 0.2 | sighup | Number of tuple inserts prior to vacuum as a fraction of reltuples. autovacuum_vacuum_insert_threshold | 1000 | sighup | Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums. autovacuum_vacuum_scale_factor | 0.2 | sighup | Number of tuple updates or deletes prior to vacuum as a fraction of reltuples. autovacuum_vacuum_threshold | 50 | sighup | Minimum number of tuple updates or deletes prior to vacuum. autovacuum_work_mem | -1 | sighup | Sets the maximum memory to be used by each autovacuum worker process.
За дополнительной информацией о параметрах автовакуума обратитесь к статье Automatic vacuuming.
Автовакуум запускается не по таймеру, а при выполнении определенных условий. Таблицы со значением relfrozenxid
, устаревшим более чем на autovacuum_freeze_max_age транзакций, всегда обрабатываются. Также, если количество кортежей, устаревших с момента последней команды VACUUM
, превышает порог vacuum threshold
, таблица будет обработана. Пороговое значение vacuum threshold
определяется следующим образом:
Где:
-
vacuum base threshold
— autovacuum_vacuum_threshold; -
vacuum scale factor
— autovacuum_vacuum_scale_factor; -
number of tuples
— pg_class.reltuples (количество живых кортежей в таблице).
Таблица также очищается, если количество кортежей, вставленных с момента последней очистки, превысило определенный порог вставки insert threshold
, который определяется как:
Где:
-
vacuum base insert threshold
— autovacuum_vacuum_insert_threshold; -
vacuum insert scale factor
— autovacuum_vacuum_insert_scale_factor; -
number of tuples
— pg_class.reltuples (количество живых кортежей в таблице).
При такой очистке часть страниц таблицы могут быть помечены как полностью видимые, и могут быть также заморожены кортежи, что уменьшит объем работы, которую нужно будет проделать при следующем вакуумировании. Для таблиц, в которых выполняются в основном операции INSERT
и практически не выполняются операций UPDATE
/DELETE
, может быть полезно снизить autovacuum_freeze_min_age таблицы, поскольку это может позволить заморозить кортежи при более раннем вакуумировании. Количество устаревших кортежей и количество добавленных кортежей передается из сборщика статистики; это приблизительное число, которое обновляется при каждой операции UPDATE
, DELETE
и INSERT
. (Значение приблизительное, поскольку некоторая информация может быть потеряна при большой нагрузке.) Если значение relfrozenxid
в таблице более старое, чем vacuum_freeze_table_age
, выполняется агрессивное вакуумирование для замораживания старых кортежей и продвижения relfrozenxid
; в противном случае сканируются только страницы, измененные с момента последнего вакуумирования.
Autovacuum использует аналогичное условие для ANALYZE
— пороговое значение analyze threshold
сравнивается с общим количеством кортежей, вставленных, обновленных или удаленных с момента последнего ANALYZE
, и определяется как:
Где:
-
analyze base threshold
— параметрautovacuum_analyze_threshold
; -
analyze scale factor
— параметрautovacuum_analyze_scale_factor
; -
number of tuples
— pg_class.reltuples (количество живых кортежей в таблице).
Родительские секционированные таблицы не хранят кортежи напрямую и, следовательно, не обрабатываются автовакуумом, но он обрабатывает секции, которые представляют собой обычные таблицы PostgreSQL. Это означает, что автовакуум не запускает ANALYZE
для родительских секционированных таблиц, что может привести к неоптимальным планам запросов, ссылающихся на статистику таких таблиц. Эту проблему можно обойти, вручную запустив команду ANALYZE
для секционированных таблиц при их первом заполнении и всякий раз, когда распределение данных в их секциях существенно меняется. См. ANALYZE для секционированных и дочерних таблиц.
Доступ к временным таблицам с помощью автовакуума невозможен, но операции VACUUM
и ANALYZE
можно выполнять с помощью SQL-команд.
Вы также можете переопределить параметры автовакуума для определенной таблицы. За дополнительной информацией обратитесь к статье Storage parameters. Если какие-либо значения определены через параметры хранения таблицы, то при обработке текущей таблицы используются они, в противном случае — глобальные параметры.