[英]How do I speed up counting rows in a PostgreSQL table?
我们需要计算 PostgreSQL 表中的行数。 在我们的例子中,不需要满足任何条件,如果能显着提高查询速度,那么获得行估计是完全可以接受的。
基本上,我们希望select count(id) from <table>
尽可能快地运行,即使这意味着无法获得准确的结果。
对于一个非常快速的估计:
SELECT reltuples FROM pg_class WHERE relname = 'my_table';
不过,有几个警告。 一方面, relname
在pg_class
不一定是唯一的。 在数据库的多个模式中可以有多个具有相同relname
表。 要明确:
SELECT reltuples::bigint FROM pg_class WHERE oid = 'my_schema.my_table'::regclass;
如果您没有对表名进行模式限定,则转换为regclass
观察当前的search_path
以选择最佳匹配。 如果该表在search_path
中的任何模式中不存在(或无法看到),您将收到一条错误消息。 请参阅手册中的对象标识符类型。
转换到bigint
可以很好地格式化real
数,尤其是对于大计数。
此外, reltuples
可能或多或少已经过时。 有一些方法可以在一定程度上弥补这一点。 使用新的和改进的选项查看稍后的答案:
对pg_stat_user_tables
的查询要慢很多倍(尽管仍然比完整计数快得多),因为这是对几个表的视图。
对于大表,计数很慢,因此您可以通过以下方式进行近似估计:
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE relname='tableName';
而且它的速度极快,结果不是浮动的,但仍然是一个接近的估计。
reltuples
是pg_class
表中的一列,它保存了“表中的行数。这只是规划器使用的估计值。它由 VACUUM、ANALYZE 和一些 DDL 命令更新,例如 CREATE INDEX”(手动)pg_class
表和大多数其他具有列或与表类似的所有内容进行编目。 这包括索引(但另见 pg_index)、序列、视图、复合类型和某些特殊关系(手册)除了在索引字段上运行 COUNT()(希望是“id”)之外 - 下一个最好的事情是使用 INSERT 上的触发器实际缓存某个表中的行数。 当然,您将改为检查缓存。
对于近似值,您可以尝试这个(来自https://wiki.postgresql.org/wiki/Count_estimate ):
select reltuples from pg_class where relname='tablename';
您可以通过简单地使用触发器 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;
并使用触发器
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(*) 一次来初始化第一条记录
您可以从系统表“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';
如果你的数据库很小,你可以像@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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.