你有没有发现,你的 Greenplum、YMatrix 数据库用了几个月后,查询变慢了、空间变大了,甚至偶尔还会报错?别急,这可能不是数据库的问题,而是它"太脏了"------是时候来一场彻底的"大扫除"了!
这篇文章将用最通俗易懂的方式,带你了解:
- 为什么数据库也需要"大扫除"?
- 如何发现那些"垃圾堆积如山"的表?
- 怎么动手清理,让数据库"焕然一新"?
- 清理不当会带来什么严重后果?
准备好了吗?我们开始吧!
🧹 一、为什么数据库需要"清理"?
在 Greenplum、YMatrix 中,清理(Vacuum) 是一个非常重要的维护操作。它就像我们打扫房间一样,把那些"没用的数据"清走,腾出空间,让数据库跑得更快、更稳。
🔍 数据库里的"垃圾"是什么?
在 Greenplum、YMatrix 中,每次执行 UPDATE
或 DELETE
操作时,并不会立刻删除旧数据。这些"旧数据"被称为 死元组(Dead Tuples) ,它们:
- 占用磁盘空间;
- 增加查询扫描的数据量;
- 导致优化器统计信息不准;
- 最严重的是:可能导致 事务 ID 回卷,让数据库"崩溃"!
🧼 清理的四大作用:
- 回收空间:清理死元组,释放磁盘空间。
- 提升性能:减少查询扫描的数据量,提高查询效率。
- 更新统计信息:帮助优化器生成更优的执行计划。
- 防止事务 ID 回卷:避免数据库"爆炸"!
🔍 二、怎么知道哪些表需要清理?
一般性指导原则
-
相对比例法:
- 当死元组数量超过活元组数量的10-20%时,通常需要关注
- 计算公式:
n_dead_tup / (n_live_tup + n_dead_tup) > 0.2
(即超过20%)
-
绝对数量法:
- 对于小表(<10万行):n_dead_tup > 1万可能有问题
- 对于中型表(10万-1000万行):n_dead_tup > 10万需要关注
- 对于大表(>1000万行):n_dead_tup > 100万应考虑清理
数据库就像一个家,我们不能每天把每个房间都打扫一遍,得先找到"最脏"的那几个房间。下面几个 SQL 查询,能帮你快速定位"垃圾堆积"的表。
📌 1. 查看死元组数量高的表
sql
SELECT
schemaname,
relname,
n_live_tup,
n_dead_tup,
(n_dead_tup::float/n_live_tup) AS dead_ratio,
pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) AS size
FROM pg_stat_user_tables
WHERE n_live_tup > 0
ORDER BY dead_ratio DESC;
👉 这个查询能告诉你哪些表里"死数据"最多,是清理的优先级对象。
查询字段解释
字段名 | 含义描述 | 关注点说明 |
---|---|---|
schemaname | 表所在的模式名(相当于命名空间) | 不同模式下的表更新频率不同,需差异化维护 |
relname | 表名 | 用于识别具体需要维护的表 |
n_live_tup | 表中"活"元组的数量(当前有效的数据行数) | 反映表的数据量大小,用于评估维护优先级 |
n_dead_tup | 表中"死"元组的数量(已删除或更新未清理的行) | 直接体现清理需求,数值越高越需优先处理 |
dead_ratio | 死元组与活元组的比率(n_dead_tup / n_live_tup ) |
最关键指标,比率越高说明表膨胀越严重 |
size | 表的当前物理大小(人类可读格式,如 1GB) | 了解该表实际占用磁盘空间,用于容量规划和优化判断 |
如何判断需要清理的表
-
优先关注 dead_ratio 高的表
- 0.2 (20%):建议执行 VACUUM
- 0.5 (50%):急需清理
- 1.0 (100%):严重膨胀,必须立即处理
-
结合绝对数量判断
- 即使比率不高,但 n_dead_tup 绝对值很大(如 >100万)的表也应考虑清理
-
考虑表大小因素
- 大表(size 值大)即使比率不高,死元组占用的绝对空间也可能很大
📌 2. 检查事务 ID 年龄(回卷风险)
vbnet
SELECT
datname,
age(datfrozenxid)AS xid_age,
mxid_age(datminmxid)AS mxid_age
FROM
pg_database
WHERE
datallowconn;
💡 xid_age
一般建议:
-
< 200 million
- 安全 :Greenplum 的
autovacuum_freeze_max_age
默认值为 200 million,这是设计上的安全阈值。
- 安全 :Greenplum 的
-
200-500 million
- 监控:虽然尚未危险,但需检查为何未触发自动冻结(可能因 autovacuum 延迟或表被排除)。
-
500-700 million
- 警告:手动干预优先级应提高,尤其是核心表。
-
700 million-1.5 billion
- 紧急:离回卷(20亿)仅剩 30% 空间,必须立即处理
-
>1.5 billion
- 灾难恢复:数据库可能已拒绝写入,需单用户模式修复:复制下载
为什么 500 million 是关键分界线?
- PostgreSQL 内部机制中,
autovacuum_freeze_max_age
(默认 200 million)和vacuum_freeze_table_age
(默认 150 million)共同控制冻结行为。 - 若事务年龄超过 500 million(默认值的 2.5 倍),说明自动维护已失效,必须人工介入。
📌 3. 查看哪些表很久没被清理过
sql
SELECT
relname,
last_vacuum,
last_autovacuum,
last_analyze,
last_autoanalyze
FROM
pg_stat_user_tables
WHERE
last_autovacuumISNULLOR last_autoanalyzeISNULLORDERBY
relname;
字段名 | 含义 | 作用说明 |
---|---|---|
relname |
表名 | 表示当前查询的表的名称 |
last_vacuum |
上次手动执行 VACUUM 的时间 |
记录用户或脚本手动对这张表执行 VACUUM 的时间 |
last_autovacuum |
上次自动清理(Autovacuum)的时间 | 记录由自动清理守护进程(Autovacuum)对该表执行 VACUUM 的时间 |
last_analyze |
上次手动执行 ANALYZE 的时间 |
记录用户或脚本手动对这张表执行 ANALYZE 的时间 |
last_autoanalyze |
上次自动分析(Autoanalyze)的时间 | 记录由自动清理守护进程对该表执行 ANALYZE 的时间 |
👉 如果一张表的 last_autovacuum
是空的,说明它可能"尘封已久",需要手动清理。
🧹 三、怎么清理数据库?
🧹 1. 自动清理(Autovacuum)
YMatrix 默认开启了 自动清理(Autovacuum) ,它就像一个"扫地机器人",自动帮你打扫卫生。
你可以在 postgresql.conf
中调整参数:
ini
# 启动
autovacuum =on
# 两次检查操作的间隔时间
autovacuum_naptime = 1min
# 一次可以同时运行多少个进程
autovacuum_max_workers = 5
# Autovacuum 进程什么时候触发 VACUUM
#实际死亡元组数(Dead Tuples)超过下方公式所计算出的有效阈值,则该表将成为 Autovacuum 候选表:autovacuum_vacuum_scale_factor * 该表总元组数 + autovacuum_vacuum_threshold
autovacuum_vacuum_scale_factor = 0.2
autovacuum_vacuum_threshold = 50
# Autovacuum 进程什么时候触发 ANALYZE
# 进行了插入/删除/更新操作的元组数超过下方公式所计算出的有效阈值的任何表都有资格进行 Autovacuum 分析:autovacuum_analyze_scale_factor * 该表总元组数 + autovacuum_analyze_threshold
autovacuum_analyze_scale_factor = 0.1
autovacuum_analyze_threshold = 50
📌 对频繁更新的表,可以单独设置更激进的策略:
ini
ALTER TABLE your_table SET (autovacuum_vacuum_scale_factor = 0.1);
ALTER TABLE your_table SET (autovacuum_vacuum_threshold = 10);
🧹 2. 手动清理(VACUUM)
对于大表或自动清理来不及处理的情况,建议手动执行:
diff
-- 清理并输出详细信息
VACUUM VERBOSE your_table;
-- 清理并更新统计信息
VACUUM ANALYZE your_table;
-- 组合操作
VACUUM (VERBOSE, ANALYZE) your_table
📌 清理建议在业务低峰期执行,避免影响性能。
🧹 3. 定期维护策略(推荐)
操作 | 频率 | 建议 |
---|---|---|
查看死元组 | 每天 | 自动脚本监控 |
执行 VACUUM | 每周 | 手动清理大表 |
执行 ANALYZE | 每周 | 更新统计信息 |
检查事务 ID 年龄 | 每月 | 避免回卷 |
检查表膨胀 | 每月 | 使用 pgstattuple |
⚠️ 四、不清理的后果有多严重?
问题 | 后果 |
---|---|
死元组堆积 | 磁盘空间浪费、查询变慢 |
表膨胀 | 存储浪费、性能下降 |
统计信息不准 | 查询计划不优、性能差 |
事务 ID 回卷 | 数据库崩溃、服务中断 |
📌 尤其是事务 ID 回卷,一旦发生,数据库可能进入"紧急模式",甚至需要停机修复,严重影响业务!
🧹 五、结语:定期"大扫除",数据库更健康!
就像我们不能一直住在一个不打扫的家里,Greenplum、YMatrix 也需要定期的维护和清理。通过本文介绍的排查方法和清理技巧,你可以轻松识别"脏乱差"的表,及时进行"打扫",让数据库保持最佳状态。
📌 小贴士:建议将清理任务写入定时脚本(如 cron),让数据库维护自动化、常态化!