#postgresql #postgresql-12 #vacuum #autovacuum
Вопрос:
У меня есть вопрос относительно настроек автовакуума / вакуума Postgres. У меня есть таблица с 4,5 миллиардами строк, и был период времени с большим количеством обновлений, в результате которых было ~ 1,5 миллиарда мертвых кортежей. На данный момент для завершения автовакуума требовалось много времени (дней). При просмотре представления pg_stat_progress_vacuum я заметил, что:
max_dead_tuples = 178956970
в результате происходит многократное повторное сканирование индекса (index_vacuum_count)
Согласно документам — max_dead_tuples-это количество мертвых кортежей, которые мы можем сохранить до того, как потребуется выполнить цикл очистки индекса на основе maintenance_work_mem.
Согласно этому, для одного мертвого кортежа требуется 6 байт пространства.
Таким образом, 6B x 178956970 = ~1 ГБ
Но мои настройки таковы
maintenance_work_mem = 20GB
autovacuum_work_mem = -1
Так что же я упускаю? почему все мои 1,5-битные мертвые кортежи не поместились в max_dead_tuples, так как 20 ГБ должно было дать достаточно места, и почему было необходимо несколько запусков?
Ответ №1:
Существует жестко заданный предел в 1 ГБ для количества мертвых кортежей за один VACUUM
цикл, см. Источник:
/*
* Return the maximum number of dead tuples we can record.
*/
static long
compute_max_dead_tuples(BlockNumber relblocks, bool useindex)
{
long maxtuples;
int vac_work_mem = IsAutoVacuumWorkerProcess() amp;amp;
autovacuum_work_mem != -1 ?
autovacuum_work_mem : maintenance_work_mem;
if (useindex)
{
maxtuples = MAXDEADTUPLES(vac_work_mem * 1024L);
maxtuples = Min(maxtuples, INT_MAX);
maxtuples = Min(maxtuples, MAXDEADTUPLES(MaxAllocSize));
/* curious coding here to ensure the multiplication can't overflow */
if ((BlockNumber) (maxtuples / LAZY_ALLOC_TUPLES) > relblocks)
maxtuples = relblocks * LAZY_ALLOC_TUPLES;
/* stay sane if small maintenance_work_mem */
maxtuples = Max(maxtuples, MaxHeapTuplesPerPage);
}
else
maxtuples = MaxHeapTuplesPerPage;
return maxtuples;
}
MaxAllocSize
определяется src/include/utils/memutils.h
как
#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
Вы можете лоббировать в списке pgsql-хакеров, чтобы увеличить лимит.