PostgreSQL参数解析autovacuum_work_mem
PostgreSQL 提供了参数 autovacuum_work_mem 用来控制每个 autovacuum 工作进程可以使用的最大内存数量。如果指定该参数时没有带单位,那么其默认单位是 KB。该参数默认值为 -1,其大小等同于 maintenance_work_mem 参数值。该参数可以在 postgresql.conf 文件中或者数据库启动的命令行中设置。
对于收集死元组的集合,autovacuum 最多只能使用 1GB 的内存,因此将 autovacuum_work_mem 设置为高于 1GB的值时,对 autovacuum 在扫描表收集的死元组数量是没有影响的。
- 默认值,-1,表示使用 maintenance_work_mem 参数的值作为本参数的值
- 最小值 1024,即 1MB,如果设置的小于 1024,自动转成 1024
- 最大值为 (INT_MAX / 1024)
在内核实现上,对于 autovacuum_work_mem 参数的使用场所有 2 处:
- 计算表最大死元组数量,在 compute_max_dead_tuples() 函数中通过 autovacuum_work_mem 参数计算使用索引场景下的表死元组的最大数量,最大数量不会超过 1GB。
- 在ginInsertCleanup() 函数中,forceCleanup 为 true 的情况下,workMemory 就是 autovacuum_work_mem 的值。当满足 accum.allocatedMemory >= workMemory * 1024L 时就会考虑将内存中的数据刷盘处理。
相关代码:
如果 autovacuum_work_mem 为 -1,则使用 maintenance_work_mem 参数的值:
autovacuum_work_mem != -1 ? autovacuum_work_mem : maintenance_work_mem;
计算表的最大死元组数量:
static long compute_max_dead_tuples(BlockNumber relblocks, bool useindex) { long maxtuples; int vac_work_mem = IsAutoVacuumWorkerProcess() && 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; }
ginInsertCleanup() 函数 forceCleanup 模式下超过最大内存限制时内存数据刷盘。
void ginInsertCleanup(GinState *ginstate, bool full_clean, bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats) { if (forceCleanup) { workMemory = (IsAutoVacuumWorkerProcess() && autovacuum_work_mem != -1) ? autovacuum_work_mem : maintenance_work_mem; } if (GinPageGetOpaque(page)->rightlink == InvalidBlockNumber || (GinPageHasFullRow(page) && (accum.allocatedMemory >= workMemory * 1024L))) { ... /* 内存刷盘 */ } }
文章评论
共0条评论