PostgreSQL 数据库大小与磁盘上已用空间不匹配

Tom*_*art 5 postgresql index-maintenance postgresql-9.6

我有一个 PostgreSQL 9.6 数据库,流量很大。我定期运行pg_repack回收表/索引中未使用的空间。在较大的表上,重新打包有时无法完成该过程,从而导致使用 PostgreSQL 报告的数据库正在使用的更多磁盘空间。

我使用以下查询来报告每个数据库的大小:

SELECT schema_name, 
       pg_size_pretty(sum(table_size)::bigint),
       (sum(table_size) / pg_database_size(current_database())) * 100 as pct
FROM (
  SELECT pg_catalog.pg_namespace.nspname as schema_name,
         pg_relation_size(pg_catalog.pg_class.oid) as table_size
  FROM   pg_catalog.pg_class
     JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid
) t
GROUP BY schema_name
ORDER BY pct DESC;

    schema_name     | pg_size_pretty |                pct                 
--------------------+----------------+------------------------------------
 production         | 605 GB         |            62.70818987165323895600
 dev                | 116 GB         |            12.05199834243206743500
 pg_toast           | 12 GB          |             1.26824870382580753200
 staging            | 12 GB          |             1.26031018275065892500
 test               | 1497 MB        |             0.15143744784303601600
 pg_catalog         | 26 MB          |         0.002621403693008641646300
 public             | 624 kB         |         0.000061661486144352849300
 information_schema | 96 kB          |         0.000009486382483746592200
 repack             | 0 bytes        | 0.00000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)

这给出了一个想法,即占用的空间应该在 周围750GB。然而实际上 PostgreSQL 的使用量几乎是原来的两倍:

$ du -hs /var/lib/postgresql/9.6/main/base/
1.3T    /var/lib/postgresql/9.6/main/base/
Run Code Online (Sandbox Code Playgroud)

问题的一部分在于pgsql_tmp,那就是占领349GB。有没有一种安全的方法可以从中删除未使用的文件pgsql_tmp

349G    /var/lib/postgresql/9.6/main/base/pgsql_tmp/
Run Code Online (Sandbox Code Playgroud)

我已经在最大的桌子上尝试过,VACUUM FULLpg_repack没有成功。摆脱浪费的磁盘空间的唯一方法似乎是将表转储到 SQL 并重新导入到干净的服务器中。

Tom*_*art 3

我已经更新了计算数据库大小的查询(包括索引):

SELECT schema_name, 
       pg_size_pretty(sum(table_size)::bigint),
       (sum(table_size) / pg_database_size(current_database())) * 100 as pct
FROM (
  SELECT pg_catalog.pg_namespace.nspname as schema_name,
         pg_total_relation_size(pg_catalog.pg_class.oid) as table_size
  FROM   pg_catalog.pg_class
     JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid
) t
GROUP BY schema_name
ORDER BY pct DESC;
Run Code Online (Sandbox Code Playgroud)

至于 tmp 文件,我已删除所有超过 1 天的文件:

find /var/lib/postgresql/9.6/main/base/pgsql_tmp/ -type f -mtime +1 -delete
Run Code Online (Sandbox Code Playgroud)

至少在我们的设置中,查询通常需要几分钟,最多几个小时。因此,超过一天的临时文件可能是某个崩溃的 postgresql 进程留下的。临时文件以进程的 PID 为后缀,就像postgresql 进程的 PID 一样pgsql_tmp13774.113774