慢速计数

来自 PostgreSQL wiki
跳转到导航跳转到搜索

索引仅扫描 已在 Postgres 9.2 中实现。 在表 可见性映射 允许的情况下提供了一些性能改进。

在 PostgreSQL 中,对表中所有行进行计数可能比较慢。

SELECT count(*) FROM tbl;

原因与 PostgreSQL 中的 MVCC 实现有关。由于多个事务可以查看数据的不同状态,这意味着“COUNT(*)”没有直接的方法可以汇总整个表的数据。PostgreSQL 必须遍历所有行才能确定可见性。这通常会导致顺序扫描,读取表中每行的信息。EXPLAIN ANALYZE 会揭示正在发生的事情。

postgres=# EXPLAIN ANALYZE SELECT COUNT(*) FROM tbl;
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=4499.00..4499.01 rows=1 width=0) (actual time=465.588..465.591 rows=1 loops=1)
   ->  Seq Scan on tbl  (cost=0.00..4249.00 rows=100000 width=0) (actual time=0.011..239.212 rows=100000 loops=1)
 Total runtime: 465.642 ms
(3 rows)

值得注意的是,只有完整计数必须如此悲观;如果用“WHERE”子句进行扩充,例如

SELECT COUNT(*) FROM tbl WHERE status = 'something';

PostgreSQL 将利用针对限制字段的可用索引来限制必须计数的记录数量。这可以大大加快此类查询的速度。PostgreSQL 仍然需要读取结果行以验证它们的存在。其他数据库系统可能只需要在这种情况下引用索引。

估计行数

PostgreSQL 可以查询表的“估计值”或“缓存”值(速度快得多)。有关详细信息,请参阅计数估计