Postgres SELECT 非常慢,EXPLAIN ANALYZE SELECT 一点也不慢

Postgres SELECT 非常慢,EXPLAIN ANALYZE SELECT 一点也不慢

不久前,我的团队注意到我们的生产服务器上的 SELECT 查询速度极慢。对于包含 100 多万行的表,这需要几分钟的时间。这些是简单的查询,例如

SELECT id, name, serno FROM public.product_facts;

相比之下,这个速度非常快:

EXPLAIN ANALYZE SELECT id, name, serno FROM public.product_facts;

后者返回如下统计数据:

Seq Scan on product_facts (cost=0.00..58167.86 rows=1339186 width=24) (actual time=0.012..435.753 rows=1399186 loops=1)
Planning time: 0.076 ms
Execution time: 708.078 ms

同样,这非常快:

SELECT COUNT (id) FROM public.product_facts;

服务器内存和 CPU 似乎没有负担。如果我在 PGadmin 的一个选项卡中运行基本的 SELECT 并让它自行运行,我可以在另一个选项卡或其他地方运行单独的操作,并且运行良好。此外,通过 检查进程和系统消耗top,我没有看到 CPU 或内存消耗过多的迹象。

网络延迟似乎也是个不太可能的罪魁祸首。网络响应时间在正常范围内。如前所述,这种奇怪的缓慢现象几周前开始出现在我们的生产服务器上,然后出现在我们的 UAT 上,现在也出现在我们的非生产实例上。缓慢似乎与记录数成正比,但适用于所有表。

对我来说,这个EXPLAIN ANALYZE案例是整个情况中最令人困惑的部分。从我对 Postgres 文档的阅读中,我了解到该ANALYZE关键字会导致服务器实际执行相关命令,然后返回该执行的分析。那么,为什么SELECT在这种情况下查询需要半秒钟,而在另一种情况下却需要一分钟以上,而且没有内存或 CPU 过载的迹象?

答案1

EXPLAIN ANALYZE SELECT...执行查询,但发送给客户端单行由执行计划组成,这意味着需要通过网络传输几百字节并在客户端进行处理。

实际的 SELECT 不EXPLAIN ANALYZE发送所有结果,这些结果已经结束一百万行这里。当客户端收到这些结果时,它必须对它们进行一些处理。

因此可以预料,第二种形式总体上会更慢,即使几分钟与 708 毫秒相比确实是一个非常显著的差异。

要解释这种差异,需要考虑两个因素:结果与网络速度的关系有多大,以及每行客户端处理的成本有多高。例如,一些图形客户端需要花费大量时间才能将结果放入列中。或者 psql 命令行客户端默认格式化输出以将列内的内容与空白填充对齐,这在某些内容上会消耗大量时间。

如果您正在使用 psql,请查看以下序列需要多少时间:

\set timing on
\pset format unaligned
SELECT id, name, serno FROM public.product_facts \g /dev/null

对于通过网络发送的结果集的大小,结果SELECT sum(octet_length(concat(id,name,serno))) FROM public.product_facts应该是一个很好的估计。

那么,为什么 SELECT 查询在这种情况下只花费半秒,而在另一种情况下却花费一分钟以上,而且没有内存或 CPU 过载的迹象?

我认为您正在查看服务器,因为网络上和/或客户端计算机上正在发生耗时的事情。服务器可能只是以网络接受结果的速度将结果推送到网络套接字,这通常不会让 CPU 处于忙碌状态。

相关内容