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

У меня есть вариант использования для одновременной вставки 100 000 строк в минуту на другом конце, несколько потоков возьмут строки и удалят их из моей таблицы. Так что определенно это создаст много мертвых кортежей в моей таблице.

Мои конфигурации автоматического вакуума

autovacuum_max_workers = 3
autovacuum_naptime = 1min
utovacuum_vacuum_scale_factor = 0.2
autovacuum_analyze_scale_factor = 0.1
autovacuum_vacuum_cost_delay = 20ms
autovacuum_vacuum_cost_limit = -1

Из pg_stat_user_tables я могу узнать, что на моей таблице работает автоочистка, но через несколько часов мой диск будет заполнен (500 ГБ), и я не смогу вставить новую строку.

со второй попытки я изменил следующую конфигурацию

autovacuum_naptime = 60min
autovacuum_vacuum_cost_delay = 0

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

Здесь я сомневаюсь, что если я изменю autovacuum_vacuum_cost_delay на ноль мс, как автоматически очистить пространство мертвых кортежей и повторно использовать его? почему он не работает должным образом, если я установил значение 20 мс?


person Mideen abdul gaffoor    schedule 11.08.2020    source источник
comment
Что вы подразумеваете под 1 отсутствием строк в минуту? Вы вставляете и удаляете только 1 строку в минуту? Насколько велики ряды?   -  person Jonathan Jacobson    schedule 11.08.2020
comment
Кроме того, если у вас возникли такие проблемы, вам следует уменьшить время сна, а не увеличивать его до 60 минут.   -  person Jonathan Jacobson    schedule 11.08.2020
comment
@JonathanJacobson Я думаю, он имел в виду лакх или 100 000 строк. en.wikipedia.org/wiki/Lakh   -  person jjanes    schedule 11.08.2020
comment
Спасибо @jjanes - я понятия не имел об этом слове   -  person Jonathan Jacobson    schedule 11.08.2020


Ответы (3)


Здесь я сомневаюсь, что если я изменю autovacuum_vacuum_cost_delay на ноль мс, как автоматически очистить пространство мертвых кортежей и повторно использовать его?

Пространство, освобожденное вакуумом, фиксируется в карте свободного пространства, откуда он раздается для повторного использования будущими INSERT.

Еще одна деталь, которую следует добавить, в 9.6 карта свободного пространства очищается только после того, как вся таблица полностью очищена, поэтому до этого момента освобожденное пространство невозможно найти. Если VACUUM никогда не доходит до самого конца, потому что он слишком медленный или прерывается, то освобождаемое им пространство не будет повторно использоваться для INSERT. Это было улучшено в v11.

почему он не работает должным образом, если я установил значение 20 мс?

Потому что вакуум не может поддерживать это значение. Значения по умолчанию для PostgreSQL часто подходят только для небольших серверов, которые, похоже, не подходят для вашего. В этой ситуации уместно и желательно изменить значения по умолчанию. Обратите внимание, что в версии 12 значение по умолчанию было снижено с 20 до 2 (и его тип был соответственно изменен с int на float, поэтому теперь вы можете указать значение с большей точностью)

person jjanes    schedule 11.08.2020
comment
Спасибо @jjanes ... есть еще одно сомнение по поводу автоматической очистки ... просто предположим, что на моем столе выполняется один поток автоматической очистки до того, как он завершит свою задачу, если придет другой поток автоматической очистки и очистит ту же таблицу, то что произойдет? для первой темы? Первый поток будет остановлен или прерван или просто сломается его работа? - person Mideen abdul gaffoor; 12.08.2020
comment
Второй просто пропустит стол. Первый продолжит. - person jjanes; 12.08.2020
comment
Если это так работает, в какой-то момент первый поток должен завершить свою задачу по очистке и освободить место, верно? если первый поток не получил какое-либо исключение? - person Mideen abdul gaffoor; 13.08.2020

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

  1. Это больше похоже на очередь задач, чем на обычную таблицу. Возможно, таблица PostgreSQL не идеальна для вашего конкретного случая использования. Вместо этого используйте решение, такое как RabbitMQ/Redis.
  2. Создавайте разделы диапазона на основе времени и очищайте старые разделы, как только они опустеют, отключив автоочистку только для этой таблицы. Подумайте о том, чтобы вообще не удалять строки и просто очистить старые разделы, если вы можете идентифицировать обработанные разделы.
  3. Подкрутите с настройками автопылесоса, чтобы он работал постоянно, без дремоты и помех. Увеличение maintenance_work_mem также может ускорить автоочистку. Возможно, вы обнаружите, что достигли предела возможностей вашего жесткого диска. В этом случае вам придется оптимизировать хранилище, чтобы оно могло вместить эти дорогостоящие операции INSERT+DELETE+autovacuum.
person Jonathan Jacobson    schedule 11.08.2020
comment
Спасибо, @Jonathan Jacobson. У меня мало знаний о RabbitMQ... Но что касается Redis, то он не подходит для нашего варианта использования, потому что размер каждой строки будет равен 0,1 МБ для моего варианта использования. Поскольку Redis использует оперативную память, хранить такой объем данных в Redis будет очень дорого, но в любом случае мы собираемся удалить данные, если возникнет какая-либо ошибка при удалении потоков, компонент должен хранить данные по крайней мере в течение нескольких часов, верно. ? - person Mideen abdul gaffoor; 12.08.2020
comment
@Mideenabdulgaffoor Создавайте раздел в час и регулярно удаляйте старые разделы. 0 удаленных кортежей. 0 работает на автовакуум. - person Jonathan Jacobson; 12.08.2020

Значение по умолчанию — 2 ms Autovacuum. Итак, ваше значение 20ms велико:

autovacuum_vacuum_cost_delay (с плавающей запятой)

Указывает значение задержки стоимости, которое будет использоваться в автоматических операциях VACUUM. Если указано -1, будет использовано обычное значение Vacuum_cost_delay. Если это значение указано без единиц измерения, оно принимается за миллисекунды. Значение по умолчанию — 2 миллисекунды. Этот параметр можно задать только в файле postgresql.conf или в командной строке сервера; но этот параметр можно переопределить для отдельных таблиц, изменив параметры хранения таблиц.

Как описано здесь Очистить :

Vacuum_cost_delay (с плавающей запятой)

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

При использовании очистки на основе стоимости подходящие значения для параметраvaco_cost_delay обычно довольно малы, возможно, менее 1 миллисекунды. Несмотря на то, что для параметраvacuum_cost_delay может быть задано значение, составляющее доли миллисекунды, такие задержки не могут быть точно измерены на старых платформах. На таких платформах увеличение потребления регулируемых ресурсов VACUUM сверх того, что вы получаете при 1 мс, потребует изменения других параметров стоимости очистки. Тем не менее, вы должны поддерживать значение вакуумной_задержки настолько малым, насколько ваша платформа будет последовательно измерять; большие задержки не помогают.

person Adrian Klaver    schedule 11.08.2020
comment
По умолчанию для autovacuum_vacuum_cost_delay в 9.6 было 20 мс, что и использует OP. - person a_horse_with_no_name; 12.08.2020