PgSQL监控死元组和自动清理状态的SQL语句执行报错ERROR: division by zero原因分析和解决方法

监控死元组和自动清理状态SQL语句,执行后报错,解决方法:

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_autoanalyze
 FROM pg_stat_user_tables
 ORDER BY n_dead_tup DESC
 LIMIT 10;

执行后报错如下:

ERROR: division by zero

怎么修改SQL语句?

这个错误是因为有些表的 n_live_tupn_dead_tup 都是零。可以使用以下几种方法修复:

方法1:使用 NULLIF() 函数(推荐)

sql 复制代码
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 语句

sql 复制代码
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() 提供默认值

sql 复制代码
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:过滤掉空表(如果业务需要)

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_autoanalyze
FROM pg_stat_user_tables
WHERE (n_live_tup + n_dead_tup) > 0  -- 只处理有数据的表
ORDER BY n_dead_tup DESC
LIMIT 10;

方法5:更完整的解决方案(包含更多信息)

sql 复制代码
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)

这是最简洁和高效的方法,它:

  1. 在除数为零时返回 NULL
  2. 避免了除零错误
  3. 代码简洁易读

执行修改后的查询就不会再出现 "division by zero" 错误了。NULLIF() 函数会在 (n_live_tup + n_dead_tup) 为零时返回 NULL,而任何数除以 NULL 都会返回 NULL,从而避免错误。

相关推荐
李广坤1 小时前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
木心月转码ing5 小时前
WSL+Cpp开发环境配置
linux
爱可生开源社区1 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
蝎子莱莱爱打怪1 天前
Centos7中一键安装K8s集群以及Rancher安装记录
运维·后端·kubernetes
崔小汤呀1 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
随逸1771 天前
《从零搭建NestJS项目》
数据库·typescript
何中应1 天前
vi编辑器使用
linux·后端·操作系统
何中应1 天前
Linux进程无法被kill
linux·后端·操作系统
何中应1 天前
rm-rf /命令操作介绍
linux·后端·操作系统
何中应1 天前
Linux常用命令
linux·操作系统