尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

PostgreSQL 存储过程+游标:每日自动统计所有模式每张表的行数

发布时间:2026/9/29 10:08:35

资讯中心
01
ARTICLE

PostgreSQL 存储过程+游标:每日自动统计所有模式每张表的行数

PostgreSQL 存储过程+游标:每日自动统计所有模式每张表的行数
1. 为什么我要把「逐表 count」这件事交给 PostgreSQL 自己干如果你手上有几十上百张表分散在多个 schema 里每隔一段时间要统计每张表的行数手工写select count(*)挨个跑一遍那基本就是体力活。表少还能忍表一多光是把schema.table拼出来、复制粘贴、记录结果就能耗掉大半天而且特别容易漏表、写错表名。我遇到的实际场景是一个数据平台里有public、ods、dwd、dws好几个 schema加起来上百张表业务方每天要看前一天各表的行数变化用来判断数据有没有正常落进来。最开始是人工跑后来改成写脚本但脚本要维护连接、要处理异常还是麻烦。最后干脆把这件事下沉到数据库里用 PostgreSQL 的存储过程加游标遍历所有 schema 下的表自动count(*)并写入一张统计结果表再配合pg_cron每天定时跑一次。这篇就交付这套可复制的方案建结果表、写存储过程、配定时任务、验证执行结果以及几个我踩过的坑。适合已经会用 PostgreSQL 基础 SQL、想把手动统计自动化的人。核心检索词就三个PostgreSQL、存储过程、游标全文围绕它们展开。2. 前置准备TaoToken 与数据库环境说明在动手写存储过程之前先把两件事说清楚一是数据库环境二是如果你在写 SQL 或调试过程中需要借助模型辅助可以用 TaoToken 来统一管理模型调用。数据库这边你需要一个能执行CREATE FUNCTION的 PostgreSQL 实例版本建议 11 及以上pg_cron对版本有要求后面会讲。当前连接的用户要有权限读取information_schema.tables也要有权限在目标 schema 下建表、建函数。如果你用的是云数据库确认一下是否允许安装pg_cron扩展有些托管实例默认不开。TaoToken 这边它是一个模型调用的统一入口官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。你在写这类存储过程、排查 SQL 报错、或者让模型帮你解释游标逻辑时可以通过它的 API 来调用模型。API 地址是 https://taotoken.net/api 注意这个地址不带 UTM 参数。如果你只是想让模型帮你看看这段 plpgsql 写得对不对用模型对话就行如果是长期写代码、跑 Agent 任务可以看 Coding Plan。提示TaoToken 是模型调用入口不替代你的数据库客户端也不替代编辑器。SQL 最终还是在你的 PostgreSQL 里执行。3. 可复制配置建表、写存储过程、配定时任务这一节是全文的核心三块内容统计结果表建表语句、带游标的存储过程、pg_cron定时配置。全部可以直接复制。3.1 建统计结果表先建一张表来存每天的统计结果。字段设计上日期、schema 名、schema表名、表名、行数、采集时间这六个够了。CREATE TABLE public.t_data_lake_statis ( statis_date date NOT NULL, schema_name varchar(255) NOT NULL, schema_table_name varchar(255) NOT NULL, table_name varchar(255) NOT NULL, table_rows numeric(255,0), collect_time timestamp(0) ); COMMENT ON COLUMN public.t_data_lake_statis.statis_date IS 统计日期; COMMENT ON COLUMN public.t_data_lake_statis.schema_name IS Schema名称; COMMENT ON COLUMN public.t_data_lake_statis.schema_table_name IS schema表名称; COMMENT ON COLUMN public.t_data_lake_statis.table_name IS 表名称; COMMENT ON COLUMN public.t_data_lake_statis.table_rows IS 表数据行数; COMMENT ON COLUMN public.t_data_lake_statis.collect_time IS 数据采集时间; COMMENT ON TABLE public.t_data_lake_statis IS 数据湖表行数日统计表;这里我把statis_date的注释从原来的「主键ID」改成了「统计日期」因为从字段含义看它就是日期不是主键。如果你要加唯一约束可以用(statis_date, schema_table_name)做联合唯一避免同一天同一张表重复插入。3.2 用游标写存储过程存储过程的思路很直接定义一个游标查出所有schema.table打开游标循环fetch每取到一个表名就动态拼count(*)语句执行把结果插入统计表循环结束关闭游标。CREATE OR REPLACE FUNCTION public.table_statistics() RETURNS int4 AS $BODY$ DECLARE table_rows int; my_table_name VARCHAR(1000); table_cursor CURSOR FOR SELECT table_schema || . || table_name AS schema_table_name FROM information_schema.tables WHERE table_schema NOT IN (pg_catalog, information_schema) AND table_type BASE TABLE; BEGIN OPEN table_cursor; DELETE FROM public.t_data_lake_statis WHERE statis_date CURRENT_DATE - 1; LOOP FETCH table_cursor INTO my_table_name; EXIT WHEN NOT FOUND; EXECUTE SELECT count(*) FROM || my_table_name INTO table_rows; INSERT INTO public.t_data_lake_statis (statis_date, schema_name, schema_table_name, table_name, table_rows, collect_time) VALUES (CURRENT_DATE - 1, SPLIT_PART(my_table_name, ., 1), my_table_name, SPLIT_PART(my_table_name, ., 2), table_rows, now()); END LOOP; CLOSE table_cursor; RETURN 1; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;和原始版本相比我做了三处调整都是实际跑的时候会遇到的第一游标查询里加了WHERE table_schema NOT IN (pg_catalog, information_schema)和table_type BASE TABLE。不加的话系统表、视图都会被统计进来count(*)对视图执行虽然不报错但结果没意义还会拖慢整体速度。第二DELETE语句保留但要注意它的语义statis_date CURRENT_DATE - 1会删掉「昨天及以后」的数据。如果你当天已经跑过一次再跑一次会先删掉再重插相当于幂等重跑。这个设计是合理的但如果你希望保留历史多次采集就要改条件。第三RETURN 1只是个占位返回值调用方不关心。如果你想让函数返回统计了多少张表可以把1换成一个计数器变量。3.3 用 pg_cron 配每日定时存储过程写好了接下来让它每天自动跑。PostgreSQL 里常用pg_cron扩展。CREATE EXTENSION IF NOT EXISTS pg_cron; SELECT cron.schedule( daily_table_statistics, 10 1 * * *, $$SELECT public.table_statistics();$$ );上面这条表示每天凌晨 1:10 执行一次。时间用 cron 表达式10 1 * * *是分、时、日、月、周。你可以按自己的时区调整pg_cron用的是数据库服务器时区建议先SHOW timezone;确认一下。如果实例不支持pg_cron退而求其次可以用操作系统的 crontab 调psql10 1 * * * psql -h 127.0.0.1 -U your_user -d your_db -c SELECT public.table_statistics();这种方式不依赖扩展但要把密码放到.pgpass里别明文写在命令里。4. 验证请求与成功结果配置完别急着等第二天先手动跑一次确认逻辑通。SELECT public.table_statistics();执行完查结果表SELECT statis_date, schema_name, table_name, table_rows, collect_time FROM public.t_data_lake_statis ORDER BY schema_name, table_name LIMIT 20;正常的话你会看到每个 schema 下的每张表都有一行table_rows是实际行数collect_time是刚才执行的时间。再核对一下总数SELECT schema_name, count(*) AS table_count, sum(table_rows) AS total_rows FROM public.t_data_lake_statis GROUP BY schema_name;拿这个结果和你手工count(*)某张表的结果对一下一致就说明游标遍历和动态 SQL 都没问题。如果你是通过 TaoToken 调模型来辅助检查这段逻辑可以让模型帮你逐行解释FETCH ... INTO和EXIT WHEN NOT FOUND的配合关系模型对话入口在 https://taotoken.net/api 配合 API Keys 使用。API Keys 管理在 https://taotoken.net/api-keys 接入文档在 https://taotoken.net/doc 。5. 本篇常见错排查这一节列几个我实际遇到过的报错和坑基本都是游标和动态 SQL 相关的。报错一relation xxx does not exist动态 SQL 里拼的表名如果带 schema一般没问题但如果某张表的 schema 名或表名包含大写字母、特殊字符information_schema.tables返回的是原始大小写而 PostgreSQL 默认把未加引号的标识符转小写就会找不到表。解决办法是在拼接时给 schema 和表名加双引号EXECUTE SELECT count(*) FROM || quote_ident(SPLIT_PART(my_table_name, ., 1)) || . || quote_ident(SPLIT_PART(my_table_name, ., 2)) INTO table_rows;报错二游标循环里count(*)特别慢表多、表大的时候逐表count(*)本身就是全表扫描慢是正常的。如果只是要估算行数可以改用pg_class.reltuples但那是估算值不精确。要精确值就得接受这个耗时建议放在业务低峰期跑。报错三pg_cron任务执行了但没数据先查cron.job_run_detailsSELECT jobid, status, return_message, start_time FROM cron.job_run_details ORDER BY start_time DESC LIMIT 10;如果status是failed看return_message。常见原因是执行用户权限不够或者函数所在的 schema 不在search_path里。可以在 cron 命令里写全public.table_statistics()。报错四重复执行导致数据翻倍如果你把DELETE那行去掉了同一天跑两次就会插两份。要么保留DELETE要么给结果表加(statis_date, schema_table_name)唯一约束用ON CONFLICT处理。报错五统计到了分区表的子表PostgreSQL 分区表在information_schema.tables里父表和子表都会出现。如果你只想统计父表需要额外过滤或者改用pg_class配合relispartition判断。这个要看你的实际需求没有统一答案。6. 后续怎么用这套统计结果数据落到t_data_lake_statis之后能做的事情就多了。你可以写个视图看每张表最近七天的行数趋势也可以配告警某张表今天行数为 0 或者比昨天跌了 50% 以上就发通知。这些都不需要再碰存储过程直接查结果表就行。如果你在写更复杂的统计逻辑、或者想让模型帮你把这段 plpgsql 改造成支持增量统计的版本可以走 TaoToken 的 Coding Plan长期编码和 Agent 场景会更顺手入口在 https://taotoken.net/coding-plan 。Claude Code 相关的接入说明在 https://taotoken.net/claude-code 。控制台在 https://taotoken.net/console 。整套方案跑通之后我最大的感受是数据库自己能干的事尽量别搬到外面用脚本干。游标加存储过程虽然写法上有点啰嗦但胜在稳定、可重复、不依赖外部环境。定时任务配好之后基本就不用管了。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。