我在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"
在决定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;