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

Posted

技术标签:

【中文标题】Postgresql 选择计数查询需要很长时间【英文标题】:Postgresql select count query takes long time 【发布时间】:2019-07-27 21:00:36 【问题描述】:

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

我正在运行select count(event_id) from events 查询。但是这个查询需要 40 秒。这对于数据库来说是很长的时间。我的表的event_id 字段是主键并被索引。为什么这需要很长时间? (服务器是ubuntu vm on vmware有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"

【问题讨论】:

编辑后的解释。 757739 块仅 600 万行似乎相当多。每个块大约有 8 行。表有多少列?或者它是否有几个长文本列(其中少于 2k)。也可能是表膨胀。如果您使用vacuum full events; 清理表,这种情况会改变吗? 表格共有 7 列。但是一列有text类型和很长的json数据。 【参考方案1】:

我知道这是一个老问题,现有答案涵盖了与此相关的绝大多数信息,但我刚刚遇到了这样一种情况,即 130 万行的表需要大约 35 秒来执行一个简单的SELECT COUNT(*) .其他解决方案都没有帮助。问题最终是表只是膨胀并且没有被清理,所以 Postgres 无法找出查询数据的最佳方式。在我运行这个之后,查询时间下降到大约 25 毫秒!

VACUUM (ANALYZE, VERBOSE, FULL) my_table_name;

希望这对其他人有帮助!

【讨论】:

亚历克,你是救命稻草!我花了几个小时试图弄清楚为什么我的 COUNT 查询需要大约 8 分钟才能运行。事实证明 Postgres 的默认真空功能还不够,需要手动真空。 很高兴为您提供帮助:)【参考方案2】:

在决定 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 来加快这些速度。

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

Faster PostgreSQL Counting

最后但同样重要的是,请始终提供扩展解释的输出,如已推荐的@a_horse_with_no_name,例如:

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

【讨论】:

以上是关于Postgresql 选择计数查询需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章

按我的第二张桌子的计数(*)排序需要很长时间

为啥即使使用仅索引扫描 PostgresQL 计数也如此缓慢

BigQuery 查询需要很长时间

选择查询需要很长时间执行 - 查询优化

查询需要很长时间才能执行 laravel

尽管成本低、基数低,但 Oracle 中的选择查询需要很长时间