1. 问题背景
在 PostgreSQL 数据库运维中,经常会遇到磁盘空间不足的告警。通过 du 命令可以快速定位到占用空间较大的数据目录,但需要进一步分析具体是哪个数据库、哪些表占用了大量空间,并制定清理方案。
2. 快速定位大容量数据库
2.1 查看数据目录空间占用
首先,登录到 PostgreSQL 服务器,查看数据目录下各数据库的占用情况:
bash
# 查看 PostgreSQL 数据目录下各子目录大小(按大小降序排序)
[root@sysm-rh96j-4 bin]# du -sh /var/lib/pgsql/16/data/base/* | sort -rh
23G /var/lib/pgsql/16/data/base/20989
12G /var/lib/pgsql/16/data/base/31130
15M /var/lib/pgsql/16/data/base/20543
13M /var/lib/pgsql/16/data/base/16385
9.7M /var/lib/pgsql/16/data/base/21570
8.1M /var/lib/pgsql/16/data/base/21573
8.1M /var/lib/pgsql/16/data/base/18499
8.0M /var/lib/pgsql/16/data/base/18506
7.8M /var/lib/pgsql/16/data/base/30929
7.7M /var/lib/pgsql/16/data/base/18470
7.6M /var/lib/pgsql/16/data/base/18921
7.5M /var/lib/pgsql/16/data/base/1
7.4M /var/lib/pgsql/16/data/base/5
7.4M /var/lib/pgsql/16/data/base/4
0 /var/lib/pgsql/16/data/base/pgsql_tmp
结果分析:
20989目录占用 23G(最大)31130目录占用 12G(次之)- 其他目录占用均小于 15M
2.2 确认数据库名称
这些数字目录对应的是数据库的 OID(对象标识符),需要连接到 PostgreSQL 查询对应的数据库名称:
sql
-- 使用 postgres 用户登录 PostgreSQL
[root@sysm-rh96j-4 bin]# sudo -u postgres psql
ユーザー postgres のパスワード:
psql (16.8)
"help"でヘルプを表示します。
-- 查询大容量目录对应的数据库
postgres=# SELECT oid, datname FROM pg_database WHERE oid IN (20989, 31130);
oid | datname
-------+------------------
20989 | dat1
31130 | dat2
(2 行)
确认结果:
- OID
20989→ 数据库dat1(占用 23G) - OID
31130→ 数据库dat2(占用 12G)
3. 分析具体表空间占用
3.1 分析 dat1 数据库
连接到 dat1 数据库,查看表空间占用:
sql
-- 切换到 dat1 数据库
postgres=# \c dat1
-- 查看表大小(按大小降序)
dat1=# SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) as table_size,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename) - pg_relation_size(schemaname || '.' || tablename)) as index_size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 10;
3.2 分析dat2数据库
sql
-- 切换到 dat2 数据库
postgres=# \c dat2
-- 查看表大小(按大小降序)
dat2=# SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as total_size,
pg_size_pretty(pg_relation_size(schemaname || '.' || tablename)) as table_size,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename) - pg_relation_size(schemaname || '.' || tablename)) as index_size
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
LIMIT 10;
4. 根本原因分析
根据排查,发现主要空间占用什么表,从而做后期清理处理