为何PostgreSQL的VACUUM仅扫描4GB数据,而数据库为58GB?
问题解答
pg_stat_progress_vacuum中的heap_blks_total仅统计用户表的堆数据块,而数据库的总大小包含了大量VACUUM不会扫描的内容,这就是两者差异的核心原因,具体拆解:
- 索引是独立存储的:你导入数据时创建的索引会占用大量空间,这部分会被算进数据库总大小,但普通VACUUM不会将索引块计入
heap_blks_total(仅在清理死元组时少量处理索引,但不会统计到这个字段里)。 - 未被使用的空闲块:如果导入时用了批量插入、预分配存储空间(比如
fillfactor配置或表空间预分配),会产生很多空块,这些块属于数据库总大小,但VACUUM只会扫描包含有效数据或死元组的堆块,空块不被统计。 - TOAST表的额外存储:大字段(如
text、bytea)超出页大小的部分会存在TOAST表中,TOAST表的块不会计入主表的heap_blks_total,但会算进数据库总大小。 - 数据库的其他组成部分:总大小还包含
pg_wal目录的WAL日志、临时文件、系统目录表、配置文件等,这些都不属于用户表堆的范畴,VACUUM完全不会扫描它们。 - 刚导入的表无大量死元组:你是空库导入数据,且导入时关闭了
autovacuum,导入后几乎没有死元组,VACUUM仅需要扫描表堆中实际存了数据的部分,不需要处理那些预分配但空的块。
你计算出的约4GB,正是VACUUM实际需要处理的用户表堆数据量,而58GB是数据库所有文件的总和,两者统计范围完全不同。
内容的提问来源于stack exchange,提问作者Fabrice Chapuis
相关产品推荐
相关产品推荐

