暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

PostgreSQL17 EXPLAIN(SERIALIZE)数据转换成本

216

PostgreSQL17 EXPLAIN(SERIALIZE)数据转换成本

我相信肯定有人之前遇到过,执行EXPLAIN ANALYZE显示的执行时间很快,但是真实执行SQL时耗时却很长,其实是因为EXPLAIN ANALYZE没有把数据真正的发送到客户端,因此也就无法估算这个过程中的网络耗时,也是造成之前提到的问题的主要原因。这个问题在PG17中有所改善,虽然并不是完全解决,但是已经很大程度的减少了EXPLAIN执行时间估算不准确的问题。

EXPLAIN(SERIALIZE)官网文档说明

我们先来看看官网文档中对于SERIALIZE的说明

包括关于序列化查询输出数据的成本的信息,即将其转换为文本或二进制格式以发送到客户端。如果数据类型输出函数非常昂贵,或者必须从离线存储中获取TOASTed值,那么这可能是常规执行查询所需时间的很大一部分。EXPLAIN的默认行为SERIALIZE NONE不执行这些转换。如果指定了SERIALIZE TEXT或SERIALIZE BINARY,则执行适当的转换,并测量执行转换所花费的时间(除非指定了TIMING OFF)。如果还指定了BUFFERS选项,那么转换中涉及的任何缓冲区访问也会被计算在内。但是,在任何情况下,EXPLAIN都不会实际将结果数据发送给客户端;因此,网络传输成本不能用这种方法来研究。只有当ANALYZE也被启用时,序列化才能被启用。如果编写SERIALIZE时不带参数,则默认为TEXT。

EXPLAIN (ANALYZE, SERIALIZE)允许收集关于查询发出的数据量的统计信息,以及将数据转换的耗时。在旧的版本中,如果不实际执行SQL语句也就无法将数据实际发送到客户端,就无法获取SQL执行的真实耗时。在有些情况,如果网络传输成本可能远大于explain 在有限在这种情况下,网络传输成本可能会淹没您想要看到的内容。特别是,该功能允许研究格式化过程中解压压缩或脱线数据的成本。

EXPLAIN ANALYZE

再看添加SERIALIZE参数之前,我们先看看没有添加这个参数的时候的执行计划。EXPLAIN ANALYZE执行查询并显示实际花费的时间,但是实际情况是并非所有操作都在此执行期间执行。先看看EXPLAIN ANALYZE执行结果。

demo=# explain analyze select * from bookings;
                                                   QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
 Seq Scan on bookings  (cost=0.00..9758.33 rows=593433 width=21) (actual time=0.019..27.817 rows=593433 loops=1)
 Planning Time: 15.441 ms
 Execution Time: 42.172 ms
(3 rows)

Time: 57.868 ms

下面我们实际执行一下SQL语句,看看执行的真实耗时。

\timing on
demo=# select * from bookings \g bookings.txt;
Time: 338.011 ms

从查询的结果可以看到真实执行的时间与explain的时间差距很大,主要是由于EXPLAIN ANALYZE不会将查询结果转换为文本或二进制形式并发送给客户端,并且节省了从各个部分组装TOASTed值的时间,因此,查询返回的行越多,误差范围就越大。

新增SERIALIZE参数

在PG17中中,我们使用serialize参数后,强制EXPLAIN将查询结果转换为文本或二进制形式并发给客户端,解压和转换的耗时显示在Serialization一栏中,下面真实执行看看效果。

demo=# EXPLAIN (analyze, serialize) SELECT * FROM bookings;
                                                   QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
 Seq Scan on bookings  (cost=0.00..9758.33 rows=593433 width=21) (actual time=0.013..28.343 rows=593433 loops=1)
 Planning Time: 0.073 ms
 Serialization: time=166.436 ms  output=29102kB  format=text
 Execution Time: 223.996 ms
(4 rows)

Time: 239.340 ms

在这里我们可以看到,在explain 中使用serialize后,计算的时间(239.340 ms)与实际执行的时间(338.011 ms),虽然仍然有一定的差距,但是比没serialize参数时计算的时间已经精确很多。explain无法精确计算执行的时间,主要是无法跟踪到从服务器发送数据到客户端耗时和磁盘写入的耗时。

总结

总的来说,EXPLAIN(SERIALIZE)小功能大作用,使用SERIALIZE参数后,强制EXPLAIN将查询结果转换为文本或二进制形式并发给客户端,使得我们对于执行的估算时间更为准确,只要我们了解有这个功能就可以帮忙我们快速定位SQL的性能问题是否与数据传输有关系。

参考

https://www.postgresql.org/docs/17/sql-explain.html

https://www.postgresql.org/docs/17/release-17.html

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=06286709e

https://postgrespro.com/blog/pgsql/5971224#commit_06286709
– / END / –

可以通过下面的方式联系我

  • 微信公众号:@墨竹札记
  • 墨天轮:@墨竹
  • 微信:wshf395062788
  • PGFans:@墨竹

如果这篇文章为你带来了灵感或启发,就请帮忙点赞收藏转发;如果文章中不严谨或者错漏之处,请及时评论指正。非常感谢!

最后修改时间:2025-02-06 10:46:55
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论