慢速计数
来自 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 可以查询表的“估计值”或“缓存”值(速度快得多)。有关详细信息,请参阅计数估计。