PgSQL监控死元组和自动清理状态的SQL语句执行报错ERROR: division by zero原因分析和解决方法
监控死元组和自动清理状态SQL语句,执行后报错,解决方法:
报错SQL:
SELECT schemaname, relname, n_live_tup, n_dead_tup,(n_dead_tup * 100.0 / (n_live_tup + n_dead_tup)) AS dead_tup_ratio,last_autovacuum, last_autoanalyzeFROM pg_stat_user_tablesORDER BY n_dead_tup DESCLIMIT 10;
执行后报错如下:
ERROR: division by zero
怎么修改SQL语句?
这个错误是因为有些表的 n_live_tup
和 n_dead_tup
都是零。可以使用以下几种方法修复:
方法1:使用 NULLIF() 函数(推荐)
SELECT schemaname, relname,n_live_tup, n_dead_tup,(n_dead_tup * 100.0 / NULLIF((n_live_tup + n_dead_tup), 0)) AS dead_tup_ratio,last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
方法2:使用 CASE 语句
SELECT schemaname, relname,n_live_tup, n_dead_tup,CASE WHEN (n_live_tup + n_dead_tup) = 0 THEN 0 ELSE (n_dead_tup * 100.0 / (n_live_tup + n_dead_tup)) END AS dead_tup_ratio,last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
方法3:使用 COALESCE() 提供默认值
SELECT schemaname, relname,n_live_tup, n_dead_tup,COALESCE((n_dead_tup * 100.0 / NULLIF((n_live_tup + n_dead_tup), 0)), 0) AS dead_tup_ratio,last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
方法4:过滤掉空表(如果业务需要)
SELECT schemaname, relname,n_live_tup, n_dead_tup,(n_dead_tup * 100.0 / (n_live_tup + n_dead_tup)) AS dead_tup_ratio,last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
WHERE (n_live_tup + n_dead_tup) > 0 -- 只处理有数据的表
ORDER BY n_dead_tup DESC
LIMIT 10;
方法5:更完整的解决方案(包含更多信息)
SELECT schemaname, relname,n_live_tup AS live_tuples,n_dead_tup AS dead_tuples,(n_live_tup + n_dead_tup) AS total_tuples,CASE WHEN (n_live_tup + n_dead_tup) = 0 THEN 0 ELSE ROUND((n_dead_tup * 100.0 / (n_live_tup + n_dead_tup))::numeric, 2) END AS dead_tup_ratio_percent,pg_size_pretty(pg_total_relation_size(schemaname || '.' || relname)) AS total_size,last_autovacuum,last_autoanalyze,age(now(), COALESCE(last_autovacuum, '1970-01-01'::timestamp)) AS since_last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
推荐使用的方法1(NULLIF)
这是最简洁和高效的方法,它:
- 在除数为零时返回 NULL
- 避免了除零错误
- 代码简洁易读
执行修改后的查询就不会再出现 “division by zero” 错误了。NULLIF() 函数会在 (n_live_tup + n_dead_tup)
为零时返回 NULL,而任何数除以 NULL 都会返回 NULL,从而避免错误。