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

时间:2013-01-28 20:19:39

标签: sql postgresql count

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

基本上,我们希望select count(id) from <table>尽可能快地运行,即使这意味着无法获得准确的结果。

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

6 个答案:

答案 0 :(得分:54)

快速估算:

SELECT reltuples FROM pg_class WHERE oid = 'my_schema.my_table'::regclass;

这优于目前提出的查询 - 包括Postgres Wiki on slow counting.中的建议(现在已更新):
relnamepg_class不是唯一的relname。在数据库的多个模式中可以有多个具有相同pg_stat_user_tables的表。在我的装置中经常出现这种情况。

regclass的查询慢了很多倍,因为这是对几张表的看法。

如果您没有对表名进行架构限定,则转化为search_path会观察当前search_path以选择最佳匹配。如果{{1}}中的任何模式中的表不存在(或无法看到),则会收到错误消息。

Object Identifier Types in the manual的详细信息。

新选项的相关答案:

答案 1 :(得分:9)

大表的计数很慢,所以你可以这样得到一个近似估计:

SELECT reltuples::bigint AS estimate 
FROM pg_class 
WHERE relname='tableName';

并且它非常快,结果不是浮动的,但仍然是一个接近估计。

  • reltuples是来自pg_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

答案 2 :(得分:6)

除了在索引字段(希望'id'是)上运行COUNT()之外 - 接下来最好的事情是使用INSERT上的触发器实际缓存某些表中的行计数。当然,您将检查缓存。

对于近似值,您可以尝试此操作(来自https://wiki.postgresql.org/wiki/Count_estimate):

select reltuples from pg_class where relname='tablename';

答案 3 :(得分:3)

只需使用触发器插入或删除后,您就可以在表中询问计数的确切值 像这样的东西

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;

并使用触发器

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();

并要求计数

select * from tcounter where table_schema =  'my_schema' and table_name = 'my_table'

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

答案 4 :(得分:2)

您可以从系统表“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';

答案 5 :(得分:0)

如果您的数据库很小,您可以估算所有表格,例如@ mike-sherrill-cat-recall建议。此命令将列出所有表。

SELECT schemaname,relname,n_live_tup 
FROM pg_stat_user_tables 
ORDER BY n_live_tup DESC;

输出将是这样的:

 schemaname |      relname       | n_live_tup
------------+--------------------+------------
 public     | items              |      21806
 public     | tags               |      11213
 public     | sessions           |       3269
 public     | users              |        266
 public     | shops              |        259
 public     | quantities         |         34
 public     | schema_migrations  |         30
 public     | locations          |          8
(8 rows)