加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

快速发现PostgreSQL中表的行计数

发布时间:2020-12-13 16:47:54 所属栏目:百科 来源:网络整理
导读:我需要知道表中的行数来计算百分比。如果总计数大于某个预定义的常数,我将使用常量值。否则,我将使用实际行数。 我可以使用SELECT count(*)FROM表。但是如果我的常数值是500,000,并且我在表中有5,000,000行,则对所有行计数将浪费很多时间。 一旦我的常数
我需要知道表中的行数来计算百分比。如果总计数大于某个预定义的常数,我将使用常量值。否则,我将使用实际行数。

我可以使用SELECT count(*)FROM表。但是如果我的常数值是500,000,并且我在表中有5,000,000行,则对所有行计数将浪费很多时间。

一旦我的常数值超过,是否可以停止计数?

我只需要确切的行数,只要它低于给定的限制。否则,如果计数高于限制,我使用极限值,并希望答案尽可能快。

这样的东西:

SELECT text,count(*),percentual_calculus()  
FROM token  
GROUP BY text  
ORDER BY count DESC;
在大表中计数行在PostgreSQL中很慢。要获得一个精确的数字,它必须做一个完整的行计数,由于 MVCC的性质。有一种方法来加快速度,如果计数不必像你的情况似乎是精确的。

而不是获取确切的计数(慢表与大表):

SELECT count(*) AS exact_count FROM myschema.mytable;

你得到这样一个接近的估计(非常快):

SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';

估计的接近程度取决于你是否足够运行ANALYZE。它通常非常接近。
见PostgreSQL Wiki FAQ。
或the dedicated wiki page for count(*) performance。

更好

PostgreSQL Wiki中的文章是有点马虎。它忽略了在一个数据库中可以有多个相同名称的表的可能性 – 在不同的模式中。为了解释:

SELECT c.reltuples::bigint AS estimate
FROM   pg_class c
JOIN   pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relname = 'mytable'
AND    n.nspname = 'myschema'

或者更好

SELECT reltuples::bigint AS estimate
FROM   pg_class
WHERE  oid = 'myschema.mytable'::regclass;

更快,更简单,更安全,更优雅。参见Object Identifier Types上的手册。

在Postgres 9.4中使用to_regclass(‘myschema.mytable’),以避免无效表名的异常:

> How to check if a table exists in a given schema

TABLESAMPLE SYSTEM (n)在Postgres 9.5

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

像@a_horse commented一样,如果pg_class中的统计信息由于某种原因而不够新,则SELECT命令的新添加子句可能很有用。例如:

>没有自动真空运行。
>在大INSERT或DELETE之后立即。
> TEMPORARY表(不包括自动真空)。

这只看到一个随机的n%(在示例中为1)选择块并计数其中的行。更大的样本增加了成本,并减少错误,你的选择。精度取决于更多的因素:

>行大小的分布。如果给定块比正常行更宽,则计数比通常低。
>死的元组或FILLFACTOR占用每个块的空间。如果在表中不均匀分布,则估计可能关闭。
>一般舍入误差。

在大多数情况下,pg_class的估计将更快更准确。

回答实际问题

First,I need to know the number of rows in that table,if the total
count is greater than some predefined constant,

是否…

… is possible at the moment the count pass my constant value,it will
stop the counting (and not wait to finish the counting to inform the
row count is greater).

是。您可以使用带有LIMIT的子查询:

SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

Postgres实际上停止计数超过给定的限制,你获得一个精确和当前计数最多n行(在示例中为500000),否则n。没有几乎像pg_class中的估计一样快。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读