PostgreSQL数据库大小(表空间大小)远大于计算的关系总和

val*_*gog 8 postgresql

你好,

我看到实际数据库大小(在HDD上和通过pg_database_size()调用显示)和大小之间存在很大差异,通过总结检索到的总关系大小来计算pg_total_relation_size().

第一个是62G,最后一个是16G(右边是最大表中已删除数据的差异)

这是一个简化的查询,可以显示我的系统上的差异:

select current_database(),
       pg_size_pretty( sum(total_relation_raw_size)::bigint ) as calculated_database_size,
       pg_size_pretty( pg_database_size(current_database()) ) as database_size   
  from (select pg_total_relation_size(relid) as total_relation_raw_size
          from pg_stat_all_tables -- this includes also system tables shared between databases
         where schemaname != 'pg_toast' 
       ) as stats;
Run Code Online (Sandbox Code Playgroud)

似乎那里有一些悬空数据.出现这种情况后,我们从该数据库中转储并完全抽空了大量未使用的数据.

PS:我想,这是某种类型的数据库损坏......从这种情况中恢复的唯一方法是切换到热备数据库......

Bob*_*obG 0

您是否有未使用的 LOB?

如果你有这样的事情:

CREATE TABLE bigobjects (
    id BIGINT NOT NULL PRIMARY KEY,
    filename VARCHAR(255) NOT NULL,
    filecontents OID NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

其次是:

\lo_import '/tmp/bigfile'
11357
INSERT INTO bigobjects VALUES (1, 'bigfile', 11357);
TRUNCATE TABLE bigobjects;
Run Code Online (Sandbox Code Playgroud)

数据库中仍会保留 LOB (id 11357)。

您可以检查数据库中所有大对象的 pg_catalog.pg_largeobject 系统目录表(建议 SELECT DISTINCT loid FROM pg_catalog.pg_largeobject 除非您想以八进制形式查看所有 LOB 数据。)

如果清除所有未使用的 LOB 并执行 VACUUM FULL,您应该会看到存储量大幅减少。我刚刚在我一直使用的个人开发数据库上尝试过此操作,发现大小从 200MB 减少到 10MB(如 pg_database_size(current_database()) 所报告。)