Postgresql автопылесос занимает слишком много времени - PullRequest
0 голосов
/ 13 июля 2020

У меня есть таблица db, которая содержит около 5-6 миллионов записей, и для выполнения очистки требуется около 20 минут. Поскольку одно поле этой таблицы обновляется очень часто, приходится иметь дело с множеством мертвых строк.

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

  1. Чтение ввода-вывода: поскольку вся таблица отсутствует в разделяемой памяти.
  2. Запись ввода-вывода: так как есть много записей для обновления .

Каким должен быть идеальный способ пылесосить этот стол? Следует ли мне увеличить autovacuum_cost_limit, чтобы разрешить больше операций за один запуск автоочистки? Но, как я вижу, он увеличится на IOPS, что опять же может снизить производительность. Сейчас у меня autovacuum_scale_factor = 0.2. Должен ли я уменьшить его? Если я уменьшу его, он будет работать чаще, хотя количество операций ввода-вывода при записи уменьшится, но это приведет к увеличению количества периодов времени с высоким уровнем ввода-вывода для чтения.

Кроме того, по мере увеличения пользовательской базы потребуется все больше и больше раз, так как размер таблицы с увеличением и вакуумом придется много читать с диска. Итак, что мне делать?

Одно из решений, которое я придумал:

  1. Отделить сильно обновленный столбец и создать отдельную таблицу.
  2. Настройка параметр, чтобы заставить его запускаться чаще, чтобы уменьшить количество операций ввода-вывода записи (как обсуждалось выше). Как обрабатывать больше операций ввода-вывода при чтении, поскольку вакуум теперь будет выполняться чаще?
  3. Объедините пункт 2 с увеличением объема ОЗУ, чтобы также уменьшить количество операций ввода-вывода при чтении.

В общем, каков подход что люди забирают, потому что я предполагаю, что у людей должен быть очень большой стол 10 ГБ или больше, который нужно пылесосить.

Ответы [ 2 ]

1 голос
/ 13 июля 2020

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

Почему тебя волнует, что это занимает 20 минут? Это вызывает что-то плохое? С такой скоростью вы можете пылесосить этот стол 72 раза в день, что, кажется, намного чаще, чем это нужно на самом деле. В версии 12 значение по умолчанию для autovacuum_vacuum_cost_delay было уменьшено в 10 раз до 2 мс. Это изменение по умолчанию было вызвано не изменениями в коде в версии 12, а осознанием того, что в большинстве случаев старые настройки по умолчанию просто устарели для современного оборудования. У меня не было бы проблем с внесением этого изменения в конфигурацию v11; но я не думаю, что это решит и вашу основную озабоченность.

У вас действительно есть проблема с объемом генерируемых вами операций ввода-вывода, или это просто предположение? Ввод-вывод выполняется в основном последовательно, но насколько это важно, будет зависеть от вашего оборудования хранения. Вы видите всплески задержки во время вакуума? Вы взимаете плату за ввод-вывод и ваш счет слишком высок? Высокий уровень ввода-вывода не является проблемой по своей сути, это проблема, только если она вызывает проблему.

В настоящее время у меня autovacuum_scale_factor = 0.2. Должен ли я уменьшить его? Если я уменьшу его, он будет работать чаще, хотя количество операций ввода-вывода записи уменьшится, но это приведет к увеличению количества периодов времени с высоким уровнем ввода-вывода при чтении. намного, если таковые имеются. Каждая страница таблицы / индекса с хотя бы одним устаревшим кортежом должна записываться во время каждого вакуума. Запись одной страницы только для удаления одного устаревшего кортежа вызовет больше записей, чем ожидание, пока не появится много устаревших кортежей, которые можно удалить одной записью. Возможно, вы будете писать немного меньше на один вакуум, но большее количество вакуума компенсирует это и, вероятно, гораздо больше, чем компенсирует это.

1 голос
/ 13 июля 2020

Есть два подхода:

  1. Уменьшите autovacuum_vacuum_cost_delay для этой таблицы, чтобы автоочистка стала быстрее. Он по-прежнему будет потреблять ввод-вывод, ЦП и ОЗУ.

  2. Установите fillfactor для таблицы на значение меньше 100 и убедитесь, что столбец, который вы часто обновляете, равен не проиндексировано. Тогда вы можете получить ГОРЯЧИЕ обновления , которые не требуют VACUUM.

...