由 John Doe 五月 14, 2025
如何评估 SELECT 查询返回的数据量对性能的影响?PostgreSQL 为 EXPLAIN 命令添加了 SERIALIZE 选项。
特性提交日志
为 EXPLAIN 命令添加 SERIALIZE 选项。
EXPLAIN (ANALYZE, SERIALIZE) 能够收集关于查询的统计信息,包括查询所输出的数据量,以及将数据转换为网络传输格式所需的时间。在此之前,如果不将数据实际发送给客户端,就无法对这些信息进行观察,但这样做的话,网络传输成本可能会掩盖你真正想要观察的内容。特别是,该功能有助于探究在格式化过程中解压缩 TOAST 压缩数据或外部存储数据的成本。
讨论:https://postgr.es/m/ca0adb0e-fa4e-c37e-1cd7-91170b18cae1@gmx.de
示例
这个特性极具意义。我们通过一个简单的例子,来看看执行整体的查询计划需要多长时间:
-- 执行带 ANALYZE 的 EXPLAIN 查询
explain (analyze) select * from simple;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Seq Scan on simple (cost=0.00..210108.80 rows=4466880 width=267) (actual time=0.016..711.977 rows=1614584 loops=1)
Planning Time: 0.198 ms
Execution Time: 749.749 ms
(3 rows)
结果还不错,但这并不是全貌。问题在于,虽然它执行了大部分查询,但并没有真正从 TOAST 列(以及其他可能的地方)将数据加载到内存中。
现在,有了这个新的 SERIALIZE 选项,就可以这样做:
-- 执行带 ANALYZE 和 SERIALIZE 的 EXPLAIN 查询
explain (analyze, serialize) select * from simple;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Seq Scan on simple (cost=0.00..210108.80 rows=4466880 width=267) (actual time=0.011..399.249 rows=1614584 loops=1)
Planning Time: 0.028 ms
Serialization: time=19479.433 ms output=28074610kB format=text
Execution Time: 19961.576 ms
(4 rows)
请注意,我们得到了一条新的信息,而且总执行成本要高得多。从表中获取数据大约只需 750 毫秒。但是从 TOAST 获取数据并生成发送给客户端的输出,却花费了近 20 秒。
另外,请注意,EXPLAIN 显示有 1614584 行数据,每行宽度为 267 字节,这大约是 410MB。
但是,序列化信息显示完整的输出量为 28074610kB,也就是 26GB!超过了 60 倍。
非常不错的体验,对于任何需要进行查询优化的人来说,这都是个好消息。非常感谢社区的所有相关人员。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/06286709ee0637ec7376329a5aa026b7682dcfe2