PostgreSQL选择计数查询需要很长时间

时间:2019-03-06 08:53:00

标签: sql postgresql postgresql-9.5

我的Postgresql 9.5数据库中有一个名为events的表。该表大约有600万条记录。

我正在运行select count(event_id) from events查询。但是此查询需要40秒。对于数据库来说这是很长的时间。我的表的event_id字段是主键并已建立索引。为什么这需要很长时间? (服务器是vmware上的ubuntu vm,具有4cpu)

说明:

"Aggregate  (cost=826305.19..826305.20 rows=1 width=0) (actual time=24739.306..24739.306 rows=1 loops=1)"
"  Buffers: shared hit=13 read=757739 dirtied=53 written=48"
"  ->  Seq Scan on event_source  (cost=0.00..812594.55 rows=5484255 width=0) (actual time=0.014..24087.050 rows=6320689 loops=1)"
"        Buffers: shared hit=13 read=757739 dirtied=53 written=48"
"Planning time: 0.369 ms"
"Execution time: 24739.364 ms"

2 个答案:

答案 0 :(得分:1)

我知道这是一个古老的问题,现有的答案涵盖了有关此问题的绝大多数信息,但是我遇到了这样一个情况:一个130万行的表需要大约35秒来执行简单的{{1 }}。其他解决方案均无济于事。问题最终是表只是just肿并且没有被清理,因此Postgres无法找出查询数据的最佳方法。我执行完此操作后,查询时间下降到大约25ms!

SELECT COUNT(*)

希望这对其他人有帮助!

答案 1 :(得分:0)

在PostgreSQL如何执行count()的决策中,有很多因素起着重要作用,但是首先,在count函数中使用的列并不重要。实际上,如果您不需要DISTINCT计数,请坚持使用count(*)

您可以尝试以下操作来强制执行仅索引扫描:

SELECT count(*) FROM (SELECT event_id FROM events) t;

...如果仍然导致顺序扫描,则索引很可能不会比表本身小很多。要仍然查看仅索引扫描的执行情况,可以使用以下命令强制执行:

SELECT count(*) FROM (SELECT event_id FROM events ORDER BY 1) t;

如果速度不是很快,您还应该考虑将PostgreSQL升级到至少9.6版,该版本引入了parallel sequential scans以加快这些速度。

此外,您可以从多种技术中进行选择以显着提高速度,以提供很大程度上取决于您的用例和要求的计数:

最后但并非最不重要的是,请始终提供扩展解释的输出,因为已经建议使用@a_horse_with_no_name,例如:

EXPLAIN (ANALYZE, BUFFERS) SELECT count(event_id) FROM events;