Перейти к основному содержимому

Регулярная очистка

примечание

Эта страница переведена при помощи нейросети GigaChat.

warning

Изменено поведение оригинальной функциональности. Изменения описаны в рамках подраздела «Доработки Pangolin».

Базы данных PostgreSQL требуют периодического обслуживания, известного как вакуумирование. Во многих случаях достаточно разрешить выполнение вакуумирования службой autovacuum, который описан в разделе раздел «Служба Autovacuum». Возможно, потребуется настроить параметры автозагрузки, описанные там, чтобы получить наилучшие результаты для ситуации. Некоторые администраторы баз данных захотят дополнить или заменить действия службы командами, управляемыми вручную VACUUM, которые обычно выполняются по расписанию сценариями cron или Планировщика задач. Чтобы правильно настроить управление вакуумированием вручную, необходимо понять проблемы, обсуждаемые в следующих нескольких подразделах. Администраторы, полагающиеся на авто-вакуумирование, все равно могут захотеть просмотреть этот материал, чтобы помочь им понять и настроить авто-вакуумирование.

Основы вакуумирования

Команда PostgreSQL VACUUM должна регулярно обрабатывать каждую таблицу по нескольким причинам:

  1. Для восстановления или повторного использования дискового пространства, занимаемого обновленными или удаленными строками.
  2. Чтобы обновить статистику данных, используемую планировщиком запросов PostgreSQL.
  3. Чтобы обновить карту видимости, которая ускоряет только индексные сканирования.
  4. Для защиты от потери очень старых данных из-за зацикливания идентификаторов транзакций или мультитранзакций.

Каждая из этих причин диктует выполнение операций VACUUM различной частоты и объема, как объясняется в следующих подразделах.

Существует два варианта VACUUM: стандартный VACUUM и VACUUM FULL. VACUUM FULL может освободить больше места на диске, но работает намного медленнее. Кроме того, стандартная форма VACUUM может выполняться параллельно с производственными операциями базы данных. (Команды, такие как SELECT, INSERT, UPDATE и DELETE будут продолжать функционировать нормально, хотя не сможете изменить определение таблицы командами, такими как ALTER TABLE, пока она очищается.) VACUUM FULL требует блокировки ACCESS EXCLUSIVE на таблице, над которой он работает, и поэтому не может быть выполнена параллельно с другим использованием таблицы. В общем, следовательно, администраторы должны стремиться использовать стандартную VACUUM и избегать VACUUM FULL.

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

Доработки Pangolin

Параметр autovacuum_disable_freeze_max_age

Начиная с версии 6.5.0 СУБД Pangolin добавлен параметр autovacuum_disable_freeze_max_age.

При включении данной настройки кластер игнорирует достижение порога для срабатывания агрессивной автоочистки с защитой от переполнения счетчика транзакций (autovacuum_freeze_max_age и autovacuum_multixact_freeze_max_age). В исключения добавлены таблицы системного каталога и шаблонные базы данных или базы данных без возможности подключения, для них использование этих параметров сохраняется, чтобы обновить их relfrozenxid и datfrozenxid.

Настройка используется для избежания блокировок больших таблиц с часто пишущимися и редко изменяющимися данными на время агрессивной автоочистки при использовании 64-битных счетчиков.

Полная заморозка таблицы все еще возможна при достижении порогов vacuum_freeze_table_age и vacuum_multixact_freeze_table_age, это позволяет обновить ее relfrozenxid, а для полного отключения заморозки их следует выставить в 2^63-1. Также при включенном параметре autovacuum_disable_freeze_max_age автовакуум не будет выбирать в приоритетном режиме самые старые таблицы и базы данных для обработки, иначе это приводило бы к работе над одними и теми же таблицами и базами с самым низким frozenxid, а остальные бы игнорировались.

Подсказка

На практике использование этого параметра может привести к постоянному увеличению горизонта транзакций из-за удерживающего relfrozenxid, например, в результате отсутствия агрессивной заморозки старой toast-таблицы. Поэтому использовать его следует с осторожностью, периодически выполняя VACUUM FREEZE во избежание накопления clog файлов из-за удержания горизонта.

Подробную информацию по использованию службы autovacuum можно просмотреть в разделе «Принцип работы автоочистки» документа «Руководство администратора».

Восстановление дискового пространства

В PostgreSQL при UPDATE или DELETE строки старая версия строки не удаляется немедленно. Этот подход необходим для получения преимуществ многоверсионного управления конкуренцией (MVCC): старую версию строки нельзя удалять до тех пор, пока она все еще потенциально видна другим транзакциям. Но в конце концов устаревшая или удаленная версия строки больше не представляет интереса ни для одной транзакции. Тогда занимаемое ею место должно быть освобождено для повторного использования новыми строками, чтобы избежать беспредельного роста требований к дисковому пространству. Это делается с помощью команды VACUUM.

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

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

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

Для тех, кто не использует autovacuum, типичный подход заключается в планировании полной VACUUM базы данных один раз в день во время периода низкого использования, дополненного более частым вакуумированием часто обновляемых таблиц при необходимости. В некоторых установках с исключительно высокой частотой обновления самые загруженные таблицы вакуумируются так часто, как каждые несколько минут. Если есть несколько баз данных в кластере, не забудьте провакуумировать каждую из них; в этом может помочь программа vacuumdb.

Совет

Простой VACUUM может быть неудовлетворительным, когда таблица содержит большое количество мертвых версий строк в результате массовой операции обновления или удаления. Если есть такая таблица и нужно вернуть избыточное дисковое пространство, которое она занимает, потребуется использовать VACUUM FULL, либо альтернативно CLUSTER или одну из вариантов переписывания таблицы ALTER TABLE. Эти команды переписывают всю новую копию таблицы и создают для нее новые индексы. Все эти опции требуют блокировки ACCESS EXCLUSIVE. Обратите внимание, что они также временно используют дополнительное дисковое пространство примерно равное размеру таблицы, поскольку старые копии таблиц и индексов не могут быть освобождены до завершения новых копий.

Если таблица, содержимое которой удаляется периодически, рассмотрите возможность сделать это с помощью TRUNCATE вместо использования DELETE за которым следует VACUUM. TRUNCATE удаляет все содержимое таблицы немедленно, без необходимости последующего выполнения VACUUM или VACUUM FULL для восстановления теперь неиспользуемого дискового пространства. Недостатком является то, что строгие семантики MVCC нарушаются.

Обновление статистики планировщика

Планировщик запросов PostgreSQL полагается на статистическую информацию о содержимом таблиц для создания хороших планов запросов. Эти статистические данные собираются командой ANALYZE, которая может быть вызвана сама по себе или как необязательный шаг в VACUUM. Важно иметь разумно точные статистические данные, иначе из-за плохого выбора планов производительность базы данных может снизиться.

Служба autovacuum, если он включен, будет автоматически выдавать команды ANALYZE каждый раз, когда содержимое таблицы достаточно изменится. Однако администраторы могут предпочесть полагаться на операции ANALYZE, запланированные вручную, особенно если известно, что обновление таблицы не повлияет на статистику «интересных» столбцов. Служба планирует ANALYZE строго в зависимости от количества вставленных или обновленных строк; он не знает, приведет ли это к значимым статистическим изменениям.

Кортежи, измененные в разделах и дочерних элементах наследования, не вызывают анализа родительской таблицы. Если родительская таблица пуста или редко изменяется, она может никогда не обрабатываться autovacuum, и статистика по дереву наследования в целом не будет собрана. Чтобы поддерживать статистику в актуальном состоянии, необходимо вручную запускать ANALYZE для родительской таблицы.

Как и в случае с вакуумированием для восстановления пространства, частое обновление статистики более полезно для сильно обновляемых таблиц, чем для редко обновляемых. Но даже для сильно обновляемой таблицы может не быть необходимости в обновлении статистики, если статистическое распределение данных меняется незначительно. Простое эмпирическое правило – подумать о том, как сильно меняются минимальные и максимальные значения столбцов таблицы. Например, столбец timestamp, содержащий время обновления строки, будет иметь постоянно увеличивающееся максимальное значение по мере добавления и обновления строк; такой столбец, вероятно, будет нуждаться в более частом обновлении статистики, чем, скажем, столбец, содержащий URL-адреса страниц, к которым обращались на веб-сайте. Столбец URL может получать изменения так же часто, но статистическое распределение его значений, вероятно, изменяется относительно медленно.

Можно запускать ANALYZE для определенных таблиц и даже только для определенных столбцов таблицы, что позволяет обновлять некоторые статистические данные чаще, чем другие, если этого требует приложение. На практике, однако, обычно лучше просто проанализировать всю базу данных, поскольку это быстрая операция. ANALYZE использует статистически случайную выборку строк таблицы, а не считывает каждую строку.

Совет

Хотя настройка частоты для каждого столбца может быть не очень продуктивной, возможно, стоит провести настройку уровня детализации статистики, собираемой ANALYZE для каждого столбца. Столбцы, которые интенсивно используются в предложениях ANALYZE и имеют сильно неравномерные распределения данных, могут потребовать более детального гистограммы данных, чем другие столбцы. Смотрите WHERE или измените значение по умолчанию для всей базы данных с помощью параметра конфигурации ALTER TABLE SET STATISTICS default_statistics_target.

Кроме того, по умолчанию доступна ограниченная информация о селективности функций. Однако, если будет создан объект статистики или индекс выражений, который использует вызов функции, будет собрана полезная статистика о функции, что может значительно улучшить планы запросов, использующих индекс выражений.

Совет

Службаautovacuum не выдает команды ANALYZE для внешних таблиц, поскольку у него нет средств определения того, как часто это может быть полезно. Если запросы требуют статистики по внешним таблицам для правильного планирования, рекомендуется вручную запускать управляемые вручную команды ANALYZE для этих таблиц по подходящему графику.

Совет

Службаautovacuum не выдает команды ANALYZE для партиционированных таблиц. Родительские объекты наследования будут анализироваться только в том случае, если сам родитель был изменен – изменения в дочерних таблицах не вызывают автоанализ основной таблицы. Если запросам требуется статистика по основным таблицам для надлежащего планирования, необходимо периодически выполнять ручное обновление ANALYZE для этих таблиц, чтобы поддерживать актуальность статистики.

Доработки Pangolin

Автоматический анализ партиционированных таблиц

Сведения

Функциональность доступна только для редакций Enterprise и Enterprise для ERP-систем.

Ранее в PostgreSQL служба autovacuum не выполняла ANALYZE для самих партиционированных таблиц — только для их партиций. Это ограничение устранено.

Теперь с помощью новой функции «Автоанализ для партиционированных таблиц» можно включить фоновый сбор статистики не только для партиций, но и для самой родительской таблицы. Это позволяет планировщику запросов принимать более обоснованные решения, опираясь на агрегированные данные по всем партициям.

Активация

Поведение регулируется новым параметром GUC autovacuum_analyze_partitioned_table (boolean), который при включении позволяет процессу autovacuum выполнять ANALYZE не только для партиций, но и для родительской партиционированной таблицы. По умолчанию имеет значение false.

Логика пороговых значений

Логика запуска ANALYZE для партиционированных (секционированных) таблиц аналогичен механизму для обычных таблиц:

analyze_threshold + analyze_scale_factor * reltuples

Но количество измененных кортежей (relchanges) суммируется по всем партициям. Полученное значение сравнивается с пороговыми значениями, заданными для самой партиционированной таблицы, которые теперь можно указать явно.

примечание

Пороговые значения для партиционированных таблиц можно задать с помощью параметров autovacuum_analyze_threshold_p и autovacuum_analyze_scale_factor_p, указанных для родительской таблицы. Если эти параметры не заданы, используются глобальные значения autovacuum_analyze_threshold и autovacuum_analyze_scale_factor.

Управление блокировками при большом числе партиций

При наличии большого числа партиций в партиционированной таблице одновременное получение множества блокировок может вызвать конфликты — особенно в случаях, когда исчерпан механизм быстрых блокировок (fast-path).

Для управления этим поведением введен параметр autovacuum_analyze_toasted_child_fraction (float8) с диапазоном от 0.0 до 1.0. Он определяет долю партиций с TOAST-таблицами, которые могут быть удержаны заблокированными во время автоанализа. Только указанная доля партиций с TOAST-таблицами будет удерживаться под AccessShareLock. Партиции без TOAST-таблиц блокируются кратковременно, и их блокировки сразу снимаются.

Прогноз количества блокировок

Количество одновременных блокировок во время ANALYZE партиционированной таблицы определяется как сумма из следующих компонентов:

  • 1 (SharedUpdateExclusiveLock на родительскую таблицу);
  • N_toasted * autovacuum_analyze_toasted_child_fraction (AccessShareLock на TOAST-партиции);
  • 1 (AccessShareLock на партицию без TOAST-партиций);
  • K (RowExclusiveLock на глобальные индексы родительской таблицы).

Где N_toasted — количество партиций с TOAST-таблицами, а K — количество глобальных индексов родительской таблицы.

Только выбранные партиции с TOAST и все партиции без TOAST участвуют в формировании статистики родительской таблицы.

Режим выбора партиций

Добавлен новый параметр хранения на уровне таблицы autovacuum_analyze_mode (enum).

Возможные значения:

  • off – отключает автоанализ для данной таблицы.
  • size – выбирает самые крупные партиции с TOAST-таблицами.
  • oid – выбирает партиции с наибольшими OID (новейшие).
  • random – выбирает партиции случайным образом.
  • gather – выполняет анализ без блокировок — только на основе уже собранной статистики по партициям.
примечание

Значения параметров size, oid, random влияют только на выбор TOAST-партиций. Если таких нет — выбираются обычные партиции, и значение параметра не имеет значения.

Режим gather

Режим gather полностью меняет поведение ANALYZE:

  • Блокировки на партициях не берутся вовсе.
  • Статистика родительской таблицы агрегируется на основе уже существующих статистик партиций.
  • Собираются поля tuples count, avg width, null fraction, n_distinct, most common values (MCV), MCV частоты, correlation.
Внимание!

При использовании режима gather точность статистики может снизиться.

Настройка количества кортежей для анализа

Для анализа партиционированных таблиц можно задать желаемое количество кортежей, которое будет использоваться при автоанализе.

Это можно сделать с помощью параметра autovacuum_analyze_desired_target_rows (int), который определяет желаемое количество кортежей для анализа партиционированной таблицы. Значение параметра может находиться в диапазоне от 1 до 2^31–1 (максимальное значение для типа int), по умолчанию – 0 (не задано).

примечание

Если для столбцов таблицы указано число статистик (через SET STATISTICS), превышающее значение параметра autovacuum_analyze_desired_target_rows, то автоанализ будет использовать указанное значение для определения количества кортежей.

Также можно настроить автоматическое определение количества кортежей для анализа партиционированной таблицы в зависимости от количества партиций. Для этого используйте параметр autovacuum_analyze_scale_partitions (boolean), при включении которого количество кортежей для анализа рассчитывается автоматически на основе количества партиций по формуле target_rows * ln(number_of_partitions + 1) или autovacuum_analyze_desired_target_rows * ln(number_of_partitions + 1), если параметр задан и его значение больше target_rows. Значение по умолчанию – false.

примечание

При необходимости итоговое количество кортежей для анализа будет автоматически снижено, чтобы не превышать лимит maintenance_work_mem.

Включение автоанализа для партиционированной таблицы:

ALTER SYSTEM SET autovacuum_analyze_partitioned_table = on;
ALTER SYSTEM SET autovacuum_analyze_toasted_child_fraction = 0.5;
ALTER SYSTEM SET autovacuum_analyze_mode = 'oid';
SELECT pg_reload_conf();
ALTER TABLE measurement SET (
autovacuum_analyze_toasted_child_fraction = 0.25,
autovacuum_analyze_mode = 'size',
autovacuum_analyze_scale_factor_p = 0.1,
autovacuum_analyze_desired_target_rows = 10000,
autovacuum_analyze_scale_partitions = true
);

Новая функциональность улучшает работу планировщика запросов для партиционированных таблиц, при этом позволяя управлять уровнем блокировок и точностью анализа.

Параметр autovacuum_disable_freeze_max_age

Добавлен параметр autovacuum_disable_freeze_max_age.

При включении данной настройки кластер игнорирует достижение порога для срабатывания агрессивной автоочистки с защитой от переполнения счетчика транзакций (autovacuum_freeze_max_age и autovacuum_multixact_freeze_max_age). В исключения добавлены таблицы системного каталога и шаблонные базы данных или базы данных без возможности подключения, для них использование этих параметров сохраняется, чтобы обновить их relfrozenxid и datfrozenxid.

Настройка используется для избежания блокировок больших таблиц с часто пишущимися и редко изменяющимися данными на время агрессивной автоочистки при использовании 64-битных счетчиков.

Полная заморозка таблицы все еще возможна при достижении порогов vacuum_freeze_table_age и vacuum_multixact_freeze_table_age, это позволяет обновить ее relfrozenxid, а для полного отключения заморозки их следует выставить в 2^63-1. Также при включенном параметре autovacuum_disable_freeze_max_age автовакуум не будет выбирать в приоритетном режиме самые старые таблицы и базы данных для обработки, иначе это приводило бы к работе над одними и теми же таблицами и базами с самым низким frozenxid, а остальные бы игнорировались.

Подсказка

На практике использование этого параметра может привести к постоянному увеличению горизонта транзакций из-за удерживающего relfrozenxid, например, в результате отсутствия агрессивной заморозки старой toast-таблицы. Поэтому использовать его следует с осторожностью, периодически выполняя VACUUM FREEZE во избежание накопления clog файлов из-за удержания горизонта.

Подробную информацию по использованию службы autovacuum можно просмотреть в разделе «Принцип работы автоочистки» документа «Руководство администратора».

Восстановление дискового пространства

В PostgreSQL при UPDATE или DELETE строки старая версия строки не удаляется немедленно. Этот подход необходим для получения преимуществ многоверсионного управления конкуренцией (MVCC, подробнее смотрите раздел «Управление конкуренцией»): старую версию строки нельзя удалять до тех пор, пока она все еще потенциально видна другим транзакциям. Но в конце концов устаревшая или удаленная версия строки больше не представляет интереса ни для одной транзакции. Тогда занимаемое ею место должно быть освобождено для повторного использования новыми строками, чтобы избежать беспредельного роста требований к дисковому пространству. Это делается с помощью команды VACUUM.

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

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

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

Для тех, кто не использует autovacuum, типичный подход заключается в планировании полной VACUUM базы данных один раз в день во время периода низкого использования, дополненного более частым вакуумированием часто обновляемых таблиц при необходимости. В некоторых установках с исключительно высокой частотой обновления самые загруженные таблицы вакуумируются так часто, как каждые несколько минут. Если есть несколько баз данных в кластере, не забудьте провакуумировать каждую из них, в этом может помочь программа vacuumdb.

Совет

Простой VACUUM может быть неудовлетворительным, когда таблица содержит большое количество мертвых версий строк в результате массовой операции обновления или удаления. Если есть такая таблица и нужно вернуть избыточное дисковое пространство, которое она занимает, потребуется использовать VACUUM FULL, либо альтернативно CLUSTER или одну из вариантов переписывания таблицы ALTER TABLE. Эти команды переписывают всю новую копию таблицы и создают для нее новые индексы. Все эти опции требуют блокировки ACCESS EXCLUSIVE. Обратите внимание, что они также временно используют дополнительное дисковое пространство примерно равное размеру таблицы, поскольку старые копии таблиц и индексов не могут быть освобождены до завершения новых копий.

Если есть таблица, содержимое которой удаляется периодически, рассмотрите возможность сделать это с помощью TRUNCATE вместо использования DELETE за которым следует VACUUM. TRUNCATE удаляет все содержимое таблицы немедленно, без необходимости последующего выполнения VACUUM или VACUUM FULL для восстановления теперь неиспользуемого дискового пространства. Недостатком является то, что строгие семантики MVCC нарушаются.

Обновление статистики планировщика

Планировщик запросов PostgreSQL полагается на статистическую информацию о содержимом таблиц для создания хороших планов запросов. Эти статистические данные собираются командой ANALYZE, которая может быть вызвана сама по себе или как необязательный шаг в VACUUM. Важно иметь разумно точные статистические данные, иначе из-за плохого выбора планов производительность базы данных может снизиться.

Служба autovacuum, если он включен, будет автоматически выдавать команды ANALYZE каждый раз, когда содержимое таблицы достаточно изменится. Однако администраторы могут предпочесть полагаться на операции ANALYZE, запланированные вручную, особенно если известно, что обновление таблицы не повлияет на статистику «интересных» столбцов. Служба планирует ANALYZE строго в зависимости от количества вставленных или обновленных строк, он не знает, приведет ли это к значимым статистическим изменениям.

Кортежи, измененные в разделах и дочерних элементах наследования, не вызывают анализа родительской таблицы. Если родительская таблица пуста или редко изменяется, она может никогда не обрабатываться autovacuum, и статистика по дереву наследования в целом не будет собрана. Чтобы поддерживать статистику в актуальном состоянии, необходимо вручную запускать ANALYZE для родительской таблицы.

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

Можно запускать ANALYZE для определенных таблиц и даже только для определенных столбцов таблицы, что позволяет обновлять некоторые статистические данные чаще, чем другие, если этого требует приложение. На практике, однако, обычно лучше просто проанализировать всю базу данных, поскольку это быстрая операция. ANALYZE использует статистически случайную выборку строк таблицы, а не считывает каждую строку.

Совет

Хотя настройка частоты для каждого столбца может быть не очень продуктивной, возможно, стоит провести настройку уровня детализации статистики, собираемой ANALYZE для каждого столбца. Столбцы, которые интенсивно используются в предложениях ANALYZE и имеют сильно неравномерные распределения данных, могут потребовать более детального гистограммы данных, чем другие столбцы. Подробнее смотрите WHERE или измените значение по умолчанию для всей базы данных с помощью параметра конфигурации ALTER TABLE SET STATISTICS default_statistics_target.

Кроме того, по умолчанию доступна ограниченная информация о селективности функций. Однако, если будет создан объект статистики или индекс выражений, который использует вызов функции, будет собрана полезная статистика о функции, что может значительно улучшить планы запросов, использующих индекс выражений.

Совет

Службаautovacuum не выдает команды ANALYZE для внешних таблиц, поскольку у него нет средств определения того, как часто это может быть полезно. Если запросы требуют статистики по внешним таблицам для правильного планирования, рекомендуется вручную запускать управляемые вручную команды ANALYZE для этих таблиц по подходящему графику.

Совет

Службаautovacuum не выдает команды ANALYZE для партиционированных таблиц. Родительские объекты наследования будут анализироваться только в том случае, если сам родитель был изменен – изменения в дочерних таблицах не вызывают автоанализ основной таблицы. Если запросам требуется статистика по основным таблицам для надлежащего планирования, необходимо периодически выполнять ручное обновление ANALYZE для этих таблиц, чтобы поддерживать актуальность статистики.

Обновление карты видимости

Вакуум ведет карту видимости для каждой таблицы, чтобы отслеживать, какие страницы содержат только кортежи, которые гарантированно видны всем активным транзакциям (и всем будущим транзакциям до тех пор, пока страница снова не будет изменена). Это имеет две цели. Во-первых, вакуум может пропустить такие страницы при следующем запуске, так как здесь нечего чистить.

Во-вторых, это позволяет PostgreSQL отвечать на некоторые запросы, используя только индекс, без обращения к базовой таблице. Поскольку индексы PostgreSQL не содержат информации о видимости кортежей, при обычном сканировании индекса для каждого совпадающего элемента индекса выполняется поиск кортежа в куче, чтобы проверить, должен ли он быть виден текущей транзакции. Сканирование только по индексу, с другой стороны, сначала проверяет карту видимости. Если известно, что все кортежи на странице видны, выборка из кучи может быть пропущена. Это наиболее полезно для больших наборов данных, где карта видимости может предотвратить обращение к диску. Карта видимости значительно меньше кучи, поэтому ее можно легко кешировать, даже если куча очень велика.

Предотвращение сбоев при зацикливании счетчика транзакций

Семантика транзакций MVCC в PostgreSQL зависит от возможности сравнения номеров идентификаторов транзакции (XID): версия строки с XID вставки больше текущего XID транзакции находится в «будущем» и не должна быть видна текущей транзакции. Но поскольку идентификаторы транзакций имеют ограниченный размер (32 бита), кластер, который работает долгое время (более 4 миллиардов транзакций), будет страдать от оборачивания идентификатора транзакции: счетчик XID оборачивается до нуля, и все сразу транзакции, которые были в прошлом, кажутся находящимися в будущем – это означает, что их вывод становится невидимым. Короче говоря, катастрофическая потеря данных. (На самом деле данные все еще там, но это слабое утешение, если не можете получить к ним доступ). Чтобы этого избежать, необходимо периодически выполнять вакуумную очистку каждой таблицы в каждой базе данных хотя бы один раз каждые два миллиарда транзакций.

Причина того, что периодическое выполнение вакуумной очистки решает проблему, заключается в том, что VACUUM пометит строки как замороженные, указывая, что они были вставлены транзакцией, которая была завершена достаточно давно, чтобы эффекты вставляющей транзакции были наверняка видны всем текущим и будущим транзакциям. Нормальные XID сравниваются с использованием арифметики по модулю-2^32^. Это означает, что для каждого нормального XID существует два миллиарда XID, которые являются «старше», и два миллиарда, которые являются «новее», другим способом сказать это то, что нормальное пространство XID является круговым без конечной точки. Поэтому, как только создается версия строки с определенным нормальным XID, эта версия строки будет казаться «в прошлом» в течение следующих двух миллиардов транзакций, независимо от того, о каком нормальном XID идет речь. Если версия строки все еще существует после более чем двух миллиардов транзакций, она внезапно появится в будущем. Чтобы предотвратить это, PostgreSQL резервирует специальный XID, FrozenTransactionId, который не подчиняется обычным правилам сравнения XID и всегда считается старше любого нормального XID. Замороженные версии строк рассматриваются так, как будто вставляющий XID был равен FrozenTransactionId, поэтому они будут казаться «в прошлом» для всех обычных транзакций независимо от проблем с оборачиванием, и такие версии строк будут действительны до тех пор, пока они не будут удалены, независимо от того, сколько времени это займет.

Примечание

В версиях PostgreSQL до 9.4 замораживание было реализовано путем фактической замены XID вставки строки наFrozenTransactionId, что было видно в системной колонке xmin строки. В новых версиях просто устанавливается бит флага, сохраняется исходный xmin строки для возможного использования при судебно-медицинской экспертизе. Однако строки с xmin, равным FrozenTransactionId (2), все еще могут быть найдены в базах данных, обновленных с помощью pg_upgrade из версий до 9.4.

Кроме того, системные каталоги могут содержать строки с xmin, равными BootstrapTransactionId, указывающими на то, что они были вставлены во время первой фазы initdb. Как и FrozenTransactionId, этот специальный XID рассматривается как более старый, чем любой нормальный XID.

vacuum_freeze_min_age контролирует, насколько старым должно быть значение XID, прежде чем строки, содержащие этот XID, будут заморожены. Увеличение этого параметра может избежать ненужной работы, если строки, которые иначе были бы заморожены, вскоре будут изменены снова, но уменьшение этого параметра увеличивает количество транзакций, которые могут пройти перед повторной очисткой таблицы.

VACUUM использует карту видимости для определения страниц таблицы, которые должны быть просканированы. Обычно она пропускает страницы, не содержащие мертвых версий строки, даже если эти страницы могут все еще содержать версии строк со старыми значениями XID. Поэтому обычные VACUUM не всегда замораживают каждую старую версию строки в таблице. Когда это происходит, VACUUM в конечном итоге потребуется выполнить агрессивную уборку aggressive vacuum, которая заморозит все подходящие незамороженные значения XID и MXID, включая те, которые находятся на всех видимых, но не полностью замороженных страницах.

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

vacuum_freeze_table_age контролирует, когда VACUUM делает это: сканируются все видимые, но не полностью замороженные страницы, если количество транзакций, прошедших с момента последнего такого сканирования, превышает vacuum_freeze_table_age минус vacuum_freeze_min_age. Установка vacuum_freeze_table_age равным нулю заставляет VACUUM всегда использовать свою агрессивную стратегию.

Максимальное время, в течение которого таблица может оставаться без уборки мусора, составляет два миллиарда транзакций минус значение vacuum_freeze_min_age на момент последней агрессивной уборки. Если бы она оставалась без уборки дольше этого времени, могло бы произойти повреждение данных. Чтобы гарантировать, что это не произойдет, автозагрузка применяется к любой таблице, которая может содержать незамороженные строки с XID старше возраста, указанного параметром конфигурации autovacuum_freeze_max_age. (Это произойдет даже в том случае, если автозагрузка отключена.)

Это означает, что если таблицу больше не убирают другим способом, автозагрузка будет применяться к ней примерно один раз каждые autovacuum_freeze_max_age минус vacuum_freeze_min_age транзакции. Для таблиц, которые регулярно очищаются от ненужных данных для восстановления пространства, это имеет мало значения. Однако для статических таблиц (включая таблицы, в которые вставляются данные, но нет обновлений или удалений) нет необходимости проводить очистку для восстановления места, поэтому может быть полезно попытаться максимизировать интервал между принудительными автозагрузками очень больших статических таблиц. Очевидно, можно сделать это либо путем увеличения autovacuum_freeze_max_age, либо уменьшения vacuum_freeze_min_age.

Эффективный максимум для vacuum_freeze_table_age составляет 0,95 * autovacuum_freeze_max_age, настройка выше этого значения будет ограничена максимальным значением. Значение больше, чем autovacuum_freeze_max_age не имело бы смысла, поскольку по достижении этого значения в любом случае вызывалась бы автоочистка для предотвращения зацикливания, а коэффициент умножения 0,95 оставляет некоторое пространство для выполнения ручной VACUUM перед тем, как это произойдет. В качестве общего правила, vacuum_freeze_table_age следует установить на значение немного ниже autovacuum_freeze_max_age, оставив достаточный зазор, чтобы регулярно запланированная VACUUM или автоподстройка, вызванная нормальной активностью удаления и обновления, выполнялась в этом окне. Установка его слишком близко может привести к антиобертонным автоподстройкам, даже если таблица недавно была очищена для восстановления пространства, тогда как более низкие значения приводят к более частому агрессивному вакуумированию.

Единственным недостатком увеличения autovacuum_freeze_max_agevacuum_freeze_table_age вместе с ним) является то, что подкаталоги pg_xact и pg_commit_ts кластера баз данных займут больше места, поскольку они должны хранить статус подтверждения и (если track_commit_timestamp включен) отметку времени всех транзакций до горизонта autovacuum_freeze_max_age. Статус подтверждения использует два бита на транзакцию, поэтому, если autovacuum_freeze_max_age установлен на максимально допустимое значение в два миллиарда, можно ожидать, что pg_xact вырастет примерно до половины гигабайта, а pg_commit_ts - примерно до 20 ГБ. Если это незначительно по сравнению с общим размером базы данных, рекомендуется установить autovacuum_freeze_max_age на максимальное допустимое значение. В противном случае установите его в зависимости от того, что готовы разрешить для хранения pg_xact и pg_commit_ts. (По умолчанию, 200 миллионов транзакций, соответствует примерно 50 Мбайт памяти pg_xact и около 2 ГБ памяти pg_commit_ts).

Одним из недостатков уменьшения vacuum_freeze_min_age является то, что он может вызвать ненужную работу VACUUM: замораживание версии строки – пустая трата времени, если строка вскоре после этого изменяется (что приводит к получению нового XID). Таким образом, настройка должна быть достаточно большой, чтобы строки не замерзали до тех пор, пока они вряд ли изменятся еще раз.

Чтобы отслеживать возраст самых старых незамерзающих XID в базе данных, VACUUM хранит статистику XID в системных таблицах pg_class и pg_database. В частности, столбец relfrozenxid строки таблицы pg_class содержит самый старый оставшийся незамерзший XID в конце последнего VACUUM, который успешно продвинул relfrozenxid (обычно последний агрессивный VACUUM). Аналогично, столбец datfrozenxid строки базы данных pg_database представляет собой нижнюю границу незамороженных XID, появляющихся в этой базе данных – это просто минимум значений relfrozenxid для каждой таблицы внутри базы данных. Удобный способ изучить эту информацию – выполнить запросы, такие как:

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');

SELECT datname, age(datfrozenxid) FROM pg_database;

Столбец age измеряет количество транзакций от XID отсечки до текущего XID транзакции.

Совет

Когда параметр командыVACUUM указан, VERBOSE печатает различные статистики о таблице. Это включает информацию о том, как relfrozenxid и relminmxid продвинулись вперед. Те же подробности появляются в журнале сервера, когда журнал автоочистки (управляемый log_autovacuum_min_duration) сообщает об операции VACUUM, выполняемой автоочисткой.

Хотя команда VACUUM сканирует в основном страницы, измененные с момента последней операции VACUUM, она также может активно сканировать некоторые полностью видимые, но не полностью замороженные страницы, пытаясь их заморозить. Однако значение relfrozenxid будет увеличено только после сканирования всех страниц таблицы, которые могут содержать незамороженные XID. Это происходит, когда значение relfrozenxid превышает значение, равное числу транзакций, запущенных командой vacuum_freeze_table_age, когда используется опция FREEZE команды VACUUM или когда все страницы, которые еще не полностью заморожены, требуют очистки для удаления устаревших версий строк. Когда команда VACUUM сканирует все страницы таблицы, которые еще не полностью заморожены, она должна установить значение age(relfrozenxid) немного больше, чем значение vacuum_freeze_min_age, которое использовалось (больше на количество транзакций, запущенных с момента запуска команды VACUUM). Команда VACUUM установит значение relfrozenxid равным самому старому XID, оставшемуся в таблице, поэтому возможно, что конечное значение будет намного новее, чем требуется. Если команда VACUUM, повышающая значение relfrozenxid, не будет выполнена для таблицы до достижения значения autovacuum_freeze_max_age, то вскоре будет принудительно выполнена автоматическая очистка таблицы.

Если по какой-то причине autovacuum не может удалить старые XID из таблицы, система начнет выдавать предупреждения, подобные этому, когда самые старые XID базы данных достигнут сорока миллионов транзакций от точки зацикливания:

WARNING:  database "mydb" must be vacuumed within 39985967 transactions
HINT: To avoid XID assignment failures, execute a database-wide VACUUM in that database.

Ручной VACUUM должен решить проблему, как предполагает подсказка, но обратите внимание, что VACUUM должен выполняться суперпользователем, иначе он не сможет обработать системные каталоги, которые предотвратят его способность продвигать базу данных datfrozenxid. Если эти предупреждения игнорируются, система откажется назначать новые XID, если осталось менее трех миллионов транзакций до зацикливания:

ERROR:  database is not accepting commands to avoid wraparound data loss in database "mydb"
HINT: Execute a database-wide VACUUM in that database.

В этом состоянии любые транзакции, уже находящиеся в процессе выполнения, могут продолжаться, но могут быть запущены только транзакции только для чтения. Операции, изменяющие записи базы данных или усекающие отношения, завершатся сбоем. Команда VACUUM все еще может быть выполнена нормально. Вопреки тому, что говорит подсказка, нет необходимости останавливать postmaster или входить в однопользовательский режим, чтобы восстановить нормальную работу. Вместо этого следуйте шагам:

  1. Устраните старые подготовленные транзакции. Их можно найти, проверив pg_prepared_xacts для строк, где age(transactionid) велико. Такие транзакции должны быть зафиксированы или отменены.
  2. Завершите длительные открытые транзакции. Их можно найти, проверив pg_stat_activity для строк, где age(backend_xid) или age(backend_xmin) велико. Такие транзакции должны быть зафиксированы или отменены, либо сеанс может быть завершен с использованием pg_terminate_backend.
  3. Удалите все старые слоты репликации. Используйте pg_stat_replication, чтобы найти слоты, где age(xmin) или age(catalog_xmin) велико. Во многих случаях такие слоты были созданы для репликации на серверы, которые больше не существуют или которые были отключены в течение длительного времени. Если удаляется слот для сервера, который все еще существует и может попытаться подключиться к этому слоту, возможно, потребуется перестроить этот репликатор.
  4. Выполните VACUUM в целевой базе данных. Простейший способ – выполнить VACUUM во всей базе данных, чтобы сократить время, необходимое для этого, также можно вручную выдать команды VACUUM для таблиц, где relminxid является самым старым. Не используйте VACUUM FULL в этом сценарии, потому что он требует XID и поэтому потерпит неудачу, за исключением режима суперпользователя, где вместо этого будет потреблен XID, тем самым увеличивая риск оборачивания идентификатора транзакции. Также не используйте VACUUM FREEZE, поскольку это приведет к выполнению большего объема работы, чем необходимо для восстановления нормальной работы.
  5. После восстановления нормальной работы убедитесь, что автоочистка правильно настроена в целевой базе данных, чтобы избежать проблем в будущем.
Примечание

В более ранних версиях иногда было необходимо остановитьpostmaster и выполнить VACUUM базы данных в однопользовательском режиме. В типичных сценариях в этом больше нет необходимости, поэтому по возможности следует избегать этих действий, поскольку они могут привести к сбою системы и повышают риски, так как отключают защиту от зацикливания идентификатора транзакции, предназначенную для предотвращения потери данных. Использовать однопользовательский режим в этом сценарии следует лишь при желании выполнить TRUNCATE или DROP ненужных таблиц, чтобы избежать необходимости выполнять для них VACUUM. Резерв в три миллиона транзакций позволяет администратору это сделать. За подробной информацией об использовании однопользовательского режима обратитесь к странице справки по postgres.

Мультитранзакции и зацикливание

Идентификаторы мультитранзакций используются для поддержки блокировки строк несколькими транзакциями. Поскольку в заголовке кортежа есть ограниченное пространство для хранения информации о блокировке, эта информация кодируется как «идентификатор нескольких транзакций», или кратко идентификатор мультитранзакции, всякий раз, когда несколько транзакций одновременно блокируют строку. Информация о том, какие идентификаторы транзакций включены в любой конкретный идентификатор мультитранзакции, хранится отдельно в подкаталоге pg_multixact, а сам идентификатор мультитранзакции появляется только в поле xmax в заголовке кортежа. Как и идентификаторы транзакций, идентификаторы мультитранзакций реализованы как 32-разрядный счетчик и соответствующее хранилище, все из которых требуют тщательного управления старением, очистки хранилища и обработки обертки. Существует отдельная область хранения, которая содержит список участников каждой мультитранзакции, который также использует 32-разрядный счетчик и который также должен управляться. Системная функция pg_get_multixact_members() может быть использована для проверки идентификаторов транзакций, связанных с идентификатором мультитакта.

При каждом сканировании любой части таблицы, VACUUM заменяет любой идентификатор мультитранзакции, который он встречает и который старше, чем vacuum_multixact_freeze_min_age, другим значением, которое может быть нулевым значением, отдельным идентификатором транзакции или более новым идентификатором мультитранзакции. Для каждой таблицы pg_class.relminmxid хранит самый старый возможный идентификатор мультитранзакции, все еще встречающийся в любой кортежной таблице. Если это значение старше, чем vacuum_multixact_freeze_table_age, то принудительно выполняется агрессивная уборка. Как обсуждалось в предыдущем разделе, агрессивная уборка означает, что будут пропущены только те страницы, которые гарантированно заморожены. Для определения его возраста pg_class.relminmxid можно использовать mxid_age().

Агрессивные VACUUM, независимо от их причины, гарантированно смогут продвинуть relminmxid таблицы. В конечном итоге, когда все таблицы во всех базах данных будут просканированы и их самые старые значения мультитранзакций будут продвинуты, информация о старых мультитранзакциях может быть удалена с диска.

В качестве устройства безопасности агрессивное сканирование уборки будет выполняться для любой таблицы, возраст мультитранзакции которой больше, чем autovacuum_multixact_freeze_max_age. Кроме того, если объем памяти, занимаемый членами мультитранзакций, превышает 2 ГБ, агрессивные сканирования уборки будут происходить чаще для всех таблиц, начиная с тех, у которых самый старый возраст мультитранзакции. Оба этих типа агрессивных сканирований будут происходить даже в том случае, если автоподборка фактически отключена.

Аналогично случаю XID, если автоподборка не удается очистить старые идентификаторы MXID из таблицы, система начнет выдавать предупреждающие сообщения, когда самые старые идентификаторы MXID базы данных достигнут сорока миллионов транзакций от точки оборачивания. И точно так же, как в случае с XID, если эти предупреждения игнорируются, система откажется генерировать новые идентификаторы MXID, как только останется менее трех миллионов до оборачивания.

Нормальная работа при исчерпании MXID может быть восстановлена почти так же, как и при исчерпании XID. Следуйте тем же шагам, что и в предыдущем разделе, но с учетом следующих различий:

  1. Выполняющиеся транзакции и подготовленные транзакции могут игнорироваться, если нет шансов, что они могут появиться в мультитранзакции.
  2. Информация о MXID не отображается напрямую в системных представлениях, таких как pg_stat_activity, однако поиск старых XID все еще является хорошим способом определения того, какие транзакции вызывают проблемы с завершением работы MXID.
  3. Исчерпание XID заблокирует все операции записи, а исчерпание MXID заблокирует только подмножество операций записи, именно те, которые связаны с блокировками строк, требующими MXID.

Служба Autovacuum

PostgreSQL имеет необязательную, но настоятельно рекомендуемую функцию под названием autovacuum (автоочистка), предназначенную для автоматизации выполнения команд VACUUM и ANALYZE. При включении autovacuum проверяет таблицы, в которых было вставлено, обновлено или удалено большое количество кортежей. Эти проверки используют средство сбора статистики, поэтому autovacuum не может быть использован, если track_counts не установлен на true. В конфигурации по умолчанию автовакуумирование включено, и соответствующие параметры конфигурации установлены соответствующим образом.

На самом деле «служба autovacuum» состоит из нескольких процессов. Существует постоянный процесс-служба, называемый запускающим процессом autovacuum, который отвечает за запуск рабочих процессов autovacuum для всех баз данных. Этот контролирующий процесс распределяет работу по времени, стараясь запускать рабочий процесс для каждой базы данных каждые autovacuum_naptime секунд. Поэтому, если установка содержит N баз данных, новый рабочий процесс будет запущен каждые autovacuum_naptime/N секунд. Одновременно разрешено работать максимум autovacuum_max_workers рабочим процессам. Если есть больше чем autovacuum_max_workers баз данных для обработки, следующая база данных будет обработана сразу после завершения работы первого рабочего процесса. Каждый рабочий процесс будет проверять каждую таблицу в своей базе данных и выполнять команды VACUUM и/или ANALYZE при необходимости. Параметр log_autovacuum_min_duration можно установить для мониторинга активности рабочих процессов autovacuum.

Если несколько больших таблиц одновременно становятся подходящими для вакуумирования в течение короткого промежутка времени, все рабочие процессы autovacuum могут оказаться занятыми вакуумированием этих таблиц в течение длительного периода. Это приведет к тому, что другие таблицы и базы данных не будут очищаться до тех пор, пока рабочий процесс не станет доступен. Нет ограничений на то, сколько рабочих процессов может находиться в одной базе данных, но рабочие процессы стараются избегать повторения работы, уже выполненной другими рабочими процессами. Обратите внимание, что количество запущенных рабочих процессов не учитывается в пределах max_connections или superuser_reserved_connections.

Таблицы, значение которых превышает autovacuum_freeze_max_age транзакций, всегда подвергаются вакуумированию (это также относится к тем таблицам, для которых максимальный возраст заморозки был изменен с помощью параметров хранения, подробнее смотрите ниже). В противном случае, если количество кортежей, устаревших с момента последнего VACUUM, превышает «порог вакуума», таблица подвергается вакууму. Порог вакуума определяется как:

Порог вакуума = Минимум (максимальный порог вакуума, базовый порог вакуума + масштабный коэффициент вакуума * количество кортежей)

где пороговое значение максимального вакуума равно autovacuum_vacuum_max_threshold, пороговое значение базового вакуума равно autovacuum_vacuum_threshold, коэффициент масштабирования вакуума равен autovacuum_vacuum_scale_factor, а количество кортежей равно pg_class.reltuples.

Таблица также подвергается вакуумированию, если количество вставленных кортежей с момента последней операции вакуумирования превысило определенный порог вставки, который определяется следующим образом:

Порог вакуумной вставки = базовый порог вакуумной вставки + коэффициент масштабирования вакуумной вставки * количество кортежей * процент незамороженной таблицы

где пороговое значение для вставки данных в результате вакуумирования равно autovacuum_vacuum_insert_threshold, коэффициент масштабирования для вставки данных в результате вакуумирования равен autovacuum_vacuum_insert_scale_factor, количество кортежей равно pg_class.reltuples, а процент незамороженной части таблицы равен 1 - pg_class.relallfrozen / pg_class.relpages. Такие вакуумирования могут позволить пометить части таблицы как полностью видимые, а также позволить заморозить кортежи, что может уменьшить объем работы, необходимой при последующих вакуумированиях. Для таблиц, которые получают операции INSERT, но не получают или почти не получают операций UPDATE/DELETE, может быть полезно уменьшить значение autovacuum_freeze_min_age для таблицы, поскольку это может позволить заморозить кортежи более ранними вакуумированиями. Количество устаревших кортежей и количество вставленных кортежей получаются из системы кумулятивной статистики. Это в конечном итоге согласованный счетчик, обновляемый каждой операцией UPDATE, DELETE и INSERT. Если значение relfrozenxid таблицы превышает значение vacuum_freeze_table_age, превышающее количество транзакций, выполняется агрессивная очистка для заморозки старых кортежей и продвижения значения relfrozenxid.

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

порог анализа = базовый порог анализа + масштабный коэффициент анализа * количество кортежей

сравнивается с общим количеством кортежей, вставленных, обновленных или удаленных с момента последнего ANALYZE.

Разделенные таблицы не хранят непосредственно кортежи и, следовательно, не обрабатываются автоочисткой. (Автоочистка обрабатывает разделы таблиц так же, как и другие таблицы.) К сожалению, это означает, что автоочистка не выполняет ANALYZE для разнесенных таблиц, и это может привести к неоптимальным планам для запросов, которые ссылаются на статистику разнесенной таблицы. можно обойти эту проблему, вручную выполнив ANALYZE на разнесенных таблицах при их первом заполнении и снова всякий раз, когда распределение данных в их разделах существенно изменяется.

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

Пороговые значения и коэффициенты масштабирования по умолчанию берутся из postgresql.conf, но их можно переопределить (и многие другие параметры управления автоматической очисткой) на основе каждой таблицы, подробнее смотрите Параметры хранилища для получения дополнительной информации. Если настройка была изменена через параметры хранения таблицы, это значение используется при обработке этой таблицы, в противном случае используются глобальные настройки. Смотрите раздел Автоматическая очистка для получения более подробной информации о глобальных настройках.

Когда выполняются несколько рабочих процессов, параметры задержки автоочистки по стоимости (смотрите раздел «Отложенная очистка на основе затрат») «уравновешиваются» между всеми выполняемыми рабочими процессами таким образом, чтобы общее воздействие ввода-вывода на систему было одинаковым независимо от количества фактически работающих рабочих процессов. Однако рабочие процессы, обрабатывающие таблицы, для которых установлены параметры хранения на уровне таблиц autovacuum_vacuum_cost_delay или autovacuum_vacuum_cost_limit, не учитываются в алгоритме балансировки.

Рабочие процессы автоочистки обычно не блокируют другие команды. Если процесс пытается получить блокировку, которая конфликтует с блокировкой SHARE UPDATE EXCLUSIVE, удерживаемой автоочисткой, получение блокировки прервет работу автоочистки. Однако если автоочистка выполняется для предотвращения повреждения транзакционной идентичности (то есть имя запроса автоочистки в представлении pg_stat_activity заканчивается на (to prevent wraparound)), автоочистка автоматически не прерывается.

Предупреждение

Регулярное выполнение команд, которые получают блокировки, конфликтующие с блокировкойSHARE UPDATE EXCLUSIVE, (например, ANALYZE), может фактически предотвратить завершение автоочистки.