【发布时间】:2020-03-17 05:47:50
【问题描述】:
我有一个臃肿的表,它的名字是“role_info”。 每天大约有 20K 的插入操作和大量的更新操作,没有删除操作。 该表现在约为 4063GB。 我们已经使用dump将表迁移到另一个数据库,新表大约62GB,所以旧数据库上的表膨胀非常严重。
PostgreSQL 版本:9.5.4
表格架构如下:
CREATE TABLE "role_info" (
"roleId" bigint NOT NULL,
"playerId" bigint NOT NULL,
"serverId" int NOT NULL,
"status" int NOT NULL,
"baseData" bytea NOT NULL,
"detailData" bytea NOT NULL,
PRIMARY KEY ("roleId")
);
CREATE INDEX "idx_role_info_serverId_playerId_roleId" ON "role_info" ("serverId", "playerId", "roleId");
“detailData”字段的平均大小约为每行 13KB。
下面有一些SQL执行结果:
1)
SELECT
relname AS name,
pg_stat_get_live_tuples(c.oid) AS lives,
pg_stat_get_dead_tuples(c.oid) AS deads
FROM pg_class c
ORDER BY deads DESC;
执行结果:
2)
SELECT *,
Pg_size_pretty(total_bytes) AS total,
Pg_size_pretty(index_bytes) AS INDEX,
Pg_size_pretty(toast_bytes) AS toast,
Pg_size_pretty(table_bytes) AS TABLE
FROM (SELECT *,
total_bytes - index_bytes - Coalesce(toast_bytes, 0) AS
table_bytes
FROM (SELECT c.oid,
nspname AS table_schema,
relname AS TABLE_NAME,
c.reltuples AS row_estimate,
Pg_total_relation_size(c.oid) AS total_bytes,
Pg_indexes_size(c.oid) AS index_bytes,
Pg_total_relation_size(reltoastrelid) AS toast_bytes
FROM pg_class c
LEFT JOIN pg_namespace n
ON n.oid = c.relnamespace
WHERE relkind = 'r') a
WHERE table_schema = 'public'
ORDER BY total_bytes DESC) a;
3)
我试图对表“role_info”进行真空处理,但它似乎被其他进程阻塞,根本没有执行。
select * from pg_stat_activity where query like '%VACUUM%' and query not like '%pg_stat_activity%';
select * from pg_locks;
我有两个问题:
- 如何处理表膨胀? autovacuum 似乎不起作用。
- 为什么真空完全堵塞?
【问题讨论】:
-
样本数据最好显示为formatted text。请参阅here,了解有关如何创建漂亮表格的一些提示。
-
您可以检查哪个会话阻止了您的真空:wiki.postgresql.org/wiki/Lock_Monitoring(您可以使用更现代的版本
pg_blocking_pids(),但在 Postgres 9.5 中不可用) - 很可能您的会话是“使用该表的事务空闲”