如何加快PostgreSQL表中的行计数?

Jua*_*oto 34 sql postgresql count

我们需要计算PostgreSQL表中的行数.在我们的例子中,不需要满足任何条件,如果显着提高查询速度,那么获得行估计是完全可以接受的.

基本上,我们希望select count(id) from <table>尽可能快地运行,即使这意味着没有得到确切的结果.

谢谢!任何建议将不胜感激!

Erw*_*ter 58

快速估算:

SELECT reltuples FROM pg_class WHERE oid = 'my_schema.my_table'::regclass;
Run Code Online (Sandbox Code Playgroud)

这优于目前提出的查询 - 包括Postgres Wiki中关于慢速计数的建议.(我现在更新了.):
relname并不是唯一的pg_class.relname在数据库的多个模式中可以有多个表相同.在我的装置中经常出现这种情况.

并且查询pg_stat_user_tables速度要慢500倍,因为这是几个表的视图.

如果您没有对表名进行模式限定,则使用强制转换来regclass观察当前search_path选择的最佳匹配.如果表中的任何模式中不存在(或无法看到),search_path则会收到错误消息.

有关手册中对象标识符类型的详细信息.

新选项的相关答案:


Ari*_*jas 9

对于大表来说,计数很慢,所以你可以通过这种方式得到一个近似估计:

SELECT reltuples::bigint AS estimate 
FROM pg_class 
WHERE relname='tableName';
Run Code Online (Sandbox Code Playgroud)

而且速度非常快,结果不是漂浮的,但仍然是一个接近估计.

  • reltuplespg_class表中的一列,它包含有关"表中行数的数据.这只是计划程序使用的估计值.它由VACUUM,ANALYZE和一些DDL命令(如CREATE INDEX")更新(手动)
  • 目录pg_class编目表以及具有列或与表类似的其他所有其他内容.这包括索引(但也参见pg_index),序列,视图,复合类型和某些特殊关系(手动)
  • "为什么"SELECT count(*)FROM bigtable;"慢?" :http://wiki.postgresql.org/wiki/FAQ#Why_is_.22SELECT_count.28.2A.29_FROM_bigtable.3B.22_slow.3F

  • 如果我愿意,可以添加where子句吗? (2认同)

Pin*_*nyM 6

除了对索引字段运行COUNT()(它希望"身份证"是) - 下一个最好的事情是实际使用缓存在INSERT触发器在某些表中的行数.当然,您将检查缓存.

您可以尝试使用此近似值(来自https://wiki.postgresql.org/wiki/Count_estimate):

select reltuples from pg_class where relname='tablename';
Run Code Online (Sandbox Code Playgroud)


Mik*_*ll' 5

您可以从系统表“pg_stat_user_tables”中获得估计。

select schemaname, relname, n_live_tup 
from pg_stat_user_tables 
where schemaname = 'your_schema_name'
and relname = 'your_table_name';
Run Code Online (Sandbox Code Playgroud)


Mar*_*ova 5

您可以通过简单地使用触发器 AFTER INSERT OR DELETE 来询问表中计数的确切值,如下所示

CREATE TABLE  tcounter(id serial primary key,table_schema text, table_name text, count serial);

insert into tcounter(table_schema, table_name,count) select 'my_schema', 'my_table', count(*) from my_schema.my_table;
Run Code Online (Sandbox Code Playgroud)

并使用触发器

CREATE OR REPLACE FUNCTION ex_count()
RETURNS trigger AS
$BODY$
BEGIN
    IF (TG_OP='INSERT') THEN
      UPDATE tcounter set count = count + 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    ELSIF  (TG_OP='DELETE') THEN
      UPDATE tcounter set count = count - 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    END IF;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

CREATE TRIGGER tg_counter  AFTER INSERT OR DELETE
  ON my_schema.my_table  FOR EACH ROW  EXECUTE PROCEDURE ex_count();
Run Code Online (Sandbox Code Playgroud)

并要求计数

select * from tcounter where table_schema =  'my_schema' and table_name = 'my_table'
Run Code Online (Sandbox Code Playgroud)

这意味着您选择 count(*) 一次来初始化第一条记录