)
文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载导读当 PostgreSQL 中的表达到数亿行规模时即使是一次普通的count(*)全表统计也可能耗时数十秒甚至更久。本文基于本仓库 postgres/get-a-quick-approximate-count-of-a-table.md 的技巧介绍如何借助pg_class系统表中的reltuples字段以亚毫秒级的速度拿到行数的近似值并补充pg_stat_user_tables.n_live_tup备选方案、ANALYZE对估算值准确度的影响以及多 schema 场景下的健壮写法。读完你可以在需要精确值与只关心数量级之间做出正确取舍。为什么 count(*) 在大表上会这么慢PostgreSQL 对count(*)的处理方式是扫描表中全部可见元组tuple逐行计数。对于数百亿、数千万乃至上亿行的表这个全表扫描过程会消耗大量的 CPU 与 I/O 时间返回的是一个精确值代价却是长时间的等待。文档给出了一个真实示例对一张约 4 亿行的events表执行 select count(*) from events; count ----------- 427462316 (1 row) Time: 55113.794 ms55 秒只是拿到精确值所需的时间下限。在生产环境中表越大、缓存命中率越低这个时间还会进一步拉长。当业务场景只需要大概有多少行时为一个精确值付出近一分钟的等待性价比很低。用 pg_class.reltuples 拿近似行数pg_class是 PostgreSQL 存储所有表、索引等关系对象的系统目录表其中reltuples字段记录了该关系表的估算行数。该估算值由ANALYZE、VACUUM以及后台autovacuum进程在采样统计时更新并非实时精确计数。查询方式如下 select reltuples::numeric as count from pg_class where relnameevents; count ----------- 427462000 (1 row) Time: 0.413 ms两个关键差异一目了然指标count(*)reltuples结果性质精确值估算值ANALYZE 采样所得执行方式全表扫描所有可见元组直接读取系统目录字段耗时4 亿行示例55113.794 ms0.413 ms适用场景需要精确行数只需数量级/大致规模文档中的示例里估算值427462000与精确值427462316相差仅数百行误差相对 4 亿的量级几乎可以忽略。而耗时从 55 秒骤降到不足半毫秒——性能提升约 10 万倍。注意reltuples的类型是real浮点数因此这里用::numeric做显式转换避免输出中出现科学计数法之类的浮点格式也更方便在应用层解析。reltuples 的准确性取决于统计时机reltuples不是实时变化的。它反映的是最近一次ANALYZE/VACUUM含 autovacuum发生时的行数采样结果。因此表刚完成批量导入、删除且尚未触发ANALYZE时reltuples可能明显滞后于实际行数数据变更频繁的表估算值会有一定偏差如果想在查询前刷新估算值可以显式执行analyze events;执行后reltuples会按最新采样更新。这也解释了为什么文档中特意强调这个结果足够告诉我需要知道的信息——它的语义定位就是估算值不能替代对账、审计等要求精确计数的场景。同时如果relname在所有 schema 中不是唯一的直接按relname过滤可能匹配到多个对象。更稳妥的写法是同时限定 schema或使用to_regclass()select reltuples::numeric as count from pg_class where relname events and relnamespace public::regnamespace; -- 或者按 schema 限定 select c.reltuples::numeric as count from pg_class c where c.oid to_regclass(public.events);to_regclass(public.events)返回该表在pg_class中的oid不存在时返回 NULL不会抛错是解析表 OID 的健壮方式。备选方案pg_stat_user_tables.n_live_tup除了直接查pg_classPostgreSQL 的统计视图pg_stat_user_tables也暴露了n_live_tup活元组估算值。它本质上来源于同一套统计基础设施写法如下select n_live_tup as count from pg_stat_user_tables where relname events;两种方案的取舍pg_class.reltuples最底层、最快任何连接都可读pg_stat_user_tables.n_live_tup带 schema 等更多上下文如schemaname、last_analyze、last_autoanalyze便于同时判断估算值的新鲜度。如果想知道上次统计是什么时候可以直接看last_analyze与last_autoanalyze据此判断估算值可信度。与仓库中其他 Postgres 技巧的联动本仓库的 Postgres 目录下有多个与统计与估算相关的技巧可以组合使用difference-between-explain-and-explain-analyze.mdexplain analyze输出的rows估算同样依赖reltuples等统计信息——估算行数越准查询计划越优inspect-progress-of-long-running-create-index.md对大表建索引时用pg_stat_progress_create_index观察进度与本文的大表操作要避免长时间阻塞是同一类运维思路count-how-many-records-there-are-of-each-type.md 与 check-table-for-any-orphaned-records.md这些场景需要精确分组计数或精确判断孤儿记录应使用标准count(*)不宜用近似值替代。这也再次印证本文的核心判断何时用近似值取决于业务是否真的需要精确数字。小结面对超大表数行数不必总是伤筋动骨需要精确值时接受count(*)的全表扫描代价只需要数量级或大致规模时查询pg_class.reltuples或pg_stat_user_tables.n_live_tup毫秒级返回通过ANALYZE主动刷新统计可以让估算值更贴近真实行数多 schema 环境下用to_regclass()或限定relnamespace避免歧义。以文档中的 4 亿行events表为例一行select reltuples::numeric from pg_class where relnameevents就把 55 秒的等待压缩到了 0.4 毫秒误差仅数百行——这正是 PostgreSQL 统计信息在运维与容量评估中的价值所在。赞分享文档教程知识库【免费下载链接】til:memo: Today I Learned项目地址https://gitcode.com/gh_mirrors/ti/til点击查看免费下载相关推荐终极免费图表数据提取工具WebPlotDigitizer5分钟快速获取精准数值还在为科研论文中的图表数据手动描点而烦恼面对PDF里的折线图只能截图粘贴WebPlotDigitizer是一款革命性的开源工具通过先进的计算机视觉技术能数据分析数据可视化计算机视觉图像处理WebPlotDigitizer数据提取工具从图表图像中快速获取数值的完整指南WebPlotDigitizer数据提取工具从图表图像中快速获取数值的完整指南 WebPlotDigitizer是一款强大的开源工具专为从图表图像中提取数值数据分析数据可视化计算机视觉图像处理Gensim 近似最近邻实战用 Annoy 加速 Word2Vec 相似度查询Gensim 近似最近邻实战用 Annoy 加速 Word2Vec 相似度查询 本教程基于 Gensim 官方示例 run_annoy.py https://人工智能NLP机器学习深度学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考