我需要知道表中的行数才能计算百分比.如果总计数大于某个预定义的常量,我将使用常量值.否则,我将使用实际的行数.

我可以用SELECT count(*) FROM table.但是,如果我的常量值是500,000,而我的表中有5,000,000,000行,那么计算所有行将浪费大量时间.

一旦超过我的常量值,就可以停止计数吗?

只要行数低于给定的限制,我就需要精确的行数.否则,如果计数高于极限,我将使用极限值,并希望尽快得到答案.

比如:

SELECT text,count(*), percentual_calculus()  
FROM token  
GROUP BY text  
ORDER BY count DESC;

推荐答案

众所周知,在PostgreSQL中,计算大表中的行速度很慢.MVCC型号需要完整的活动行数才能获得精确的数字.如果not的计数必须是exact,就像你的情况一样,那么speed this up dramatically有变通办法.

(请记住,在并发写负载下,即使是"精确"计数也可能在到达时失效.)

精确计数

Slow for big tables.
With concurrent write operations, it may be outdated the moment you get it.

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

非常fast:

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

通常,估计值非常接近.距离有多近取决于ANALYZEVACUUM是否足够运行,其中"足够"由表的写入活动级别定义.

Safer estimate

以上内容忽略了在一个数据库中使用相同名称的多个表的可能性——在不同的模式中.为了说明这一点:

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';

演员阵容为bigint,很好地格式化了real的数字,特别是对于大计数.

更好的估计

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

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

在Postgres 9.4+中,将'myschema.mytable'::regclass替换为to_regclass('myschema.mytable'),以不获取任何内容,而不是无效表名的异常.见:

更好的估计(几乎不增加成本)

我们可以做博士后规划师做的事情.引用Row Estimation Examples in the manual条:

这些数字是上一个VACUUMANALYZE的最新数字

Postgres使用src/backend/utils/adt/plancat.c中定义的estimate_rel_size,这也涵盖了pg_class中没有数据的情况,因为关系从未被清空.我们可以在SQL中执行类似的操作:

Minimal form

SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
FROM   pg_class
WHERE  oid = 'mytable'::regclass;  -- your table here

Safe and explicit

SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
             WHEN c.relpages = 0 THEN float8 '0'  -- empty table
             ELSE c.reltuples / c.relpages END
      * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
       )::bigint
FROM   pg_class c
WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here

不会与空桌子和从未见过VACUUMANALYZE的桌子决裂.The manual on pg_class:

如果该表从未被抽真空或分析过,则reltuples包含-1,表示行数未知.

如果该查询返回NULL,则对该表运行ANALYZEVACUUM并重复.(或者,您也可以像Postgres那样基于列类型估计行宽,但这既繁琐又容易出错.)

如果此查询返回0,则表似乎为空.但我想确认一下.(也许可以判断一下你的autovacuum设置.)

通常,block_size等于8192.current_setting('block_size')::int涵盖了罕见的例外情况.

表和模式限定使其不受任何search_path和范围的影响.

不管是哪种方式,查询都会持续进行<;对我来说是0.1毫秒.

更多网络资源:


TABLESAMPLE SYSTEM (n) in Postgres 9.5+

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

@a_horse commented一样,如果pg_class中的统计信息由于某种原因不够及时,SELECT命令的added子句也会很有用.例如:

  • 没有autovacuum人在 run .
  • 就在INSERT/UPDATE/DELETE大爆炸之后.
  • TEMPORARY张桌子(autovacuum不包括在内).

这只会查看随机 Select 的n%(示例中为1)块,并对其中的行进行计数.更大的样本会增加成本并减少误差,你可以 Select .准确性取决于更多因素:

  • 行大小的分布.如果一个给定的块恰好包含比平常更宽的行,那么计数就会比平常低,等等.
  • 死元组或FILLFACTOR占用每个块的空间.如果在整个表格中分布不均,估计值可能会偏离.
  • 一般舍入误差.

通常,从pg_class开始的估计会更快、更准确.

对实际问题的回答

首先,我需要知道表中的行数,如果总数

以及是否...

... 当计数通过我的常量值时,它将是可能的

Yes.你可以使用subquery with 100:

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

Postgres actually stops counting超出给定限制,最多n行(本例中为500000行)的计数为exact and current,否则为n.不过,速度远不及pg_class年的估计.

Sql相关问答推荐

如何编写SQL查询,在2024年每月的第一个日期输出货币?

Snowflake - SQL查询-登录注销-总工作时间

如何将多个 Select 查询从一个表中组合出来

删除MariaDB数据库中的JSON数据

如何根据同一表中某一列中的值重新排列行(仅输出它们)(重新排序)?

如何从JSON数组中 Select 多个值

关于Postgres横向联接的谓词

使用generate_series()时,LEFT联接缺少日期/间隔

优化Postgres搜索未知长度的子串

在UNION查询中查找MIN

Haystack针相交-在元素最多的Haystack中查找集合

统计PostgreSQL中前10个最大大小表的行数

SQL按组 Select 最小值,当值不存在时为Null

仅当 SQL Server 中的表为开时,才在存储过程中使用更改跟踪

如何在 case 语句中使用聚合?

使用in和and运算符过滤记录的条件

为什么 get_json_object() 无法从存储在 Hive SQL 表中的 JSON 中提取值?

使用 GROUP BY 时如何创建其他组?

String_Split 多列

在给定列中具有特定值的行与 SQL 中的总行数的比率