微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Postgres 中加速 autovacuum

如何解决在 Postgres 中加速 autovacuum

我有一个关于 Postgres 自动真空/真空设置的问题。 我有一个包含 45 亿行的表,有一段时间进行了大量更新,导致大约 15 亿个死元组。此时 autovacuum 需要很长时间(几天)才能完成。 在查看 pg_stat_progress_vacuum 视图时,我注意到:

max_dead_tuples = 178956970

导致多次索引重新扫描(index_vacuum_count)
根据 docs - max_dead_tuples 是我们可以在需要执行索引真空循环之前存储的死元组数量,基于维护工作内存。
根据 this一个元组需要 6 个字节的空间。
所以 6B x 178956970 = ~1GB
但我的设置是

maintenance_work_mem = 20GB
autovacuum_work_mem = -1

那我错过了什么?为什么我的 1.5b 死元组不能全部放入 max_dead_tuples,因为 20GB 应该提供足够的空间,为什么需要多次运行?

解决方法

对于一个 VACUUM 周期内的死元组数量有 1GB 的硬编码限制,参见 the source

/*
 * 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() &&
    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;
}

MaxAllocSizesrc/include/utils/memutils.h 中定义为

#define MaxAllocSize   ((Size) 0x3fffffff) /* 1 gigabyte - 1 */

您可以游说 pgsql-hackers 列表以增加限制。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。