PostgreSQL 教程: 测算查询返回的数据量及其网络传输成本

七月 26, 2024

摘要:在本教程中,您将学习如何测算查询返回的数据量和花费的时间。

目录

介绍

PostgreSQL 17 引入了 EXPLAIN (ANALYZE, SERIALIZE),它允许收集一些统计信息,包括查询发出的数据量,以及将数据转换为线上格式所花费的时间。以前,如果不实际将数据发送到客户端,就无法对此进行调查,在这种情况下,网络传输成本可能会掩盖您想要看到的内容。具体而言,该特性允许调查在格式化过程中,对压缩或线外数据进行 TOAST 还原处理的成本。

示例

让我们来看一个简单的例子,首先开始设置一个小的测试用例:

CREATE TABLE t_large (id integer, str text);

INSERT INTO t_large (id, str)
  SELECT i, repeat(chr(65 + mod(i, 26)), 8000) as str
    FROM generate_series(1, 300000) AS s(i);

这是一个包含了 300000 行的简单表。让我们看看获取所有记录需要多长时间:

EXPLAIN (analyze) SELECT * FROM t_large;
                                                   QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
 Seq Scan on t_large  (cost=0.00..8173.00 rows=300000 width=107) (actual time=0.019..36.160 rows=300000 loops=1)
 Planning Time: 0.179 ms
 Execution Time: 46.754 ms
(3 rows)

还不错。但这还不是全貌。问题是,虽然它确实运行了大部分查询,但它并没有真正从 TOAST 列(可能还有其他一些地方)获取数据到内存中。

现在,有了这个新的 SERIALIZE 选项,我们可以这样做:

EXPLAIN (analyze, serialize) SELECT * FROM t_large;
                                                   QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
 Seq Scan on t_large  (cost=0.00..8173.00 rows=300000 width=107) (actual time=0.027..38.856 rows=300000 loops=1)
 Planning Time: 0.063 ms
 Serialization: time=913.841 ms  output=2348329kB  format=text
 Execution Time: 971.575 ms
(4 rows)

请注意,我们得到了一条新的输出行,还得到了更高的总执行成本。从表中获取数据很简单,只需大约 47 毫秒。但是从 TOAST 获取数据,并生成输出结果以发送给客户端,这个过程花了将近 1 秒钟。

另外,请注意,EXPLAIN 输出显示了 rows=300000width=107,也就是大约 30MB。

但是,序列化时显示了全量输出为 output=2348329kB,也就是 2.24GB!这比原来超出了 76 倍。

对于任何从事查询优化的人来说,这都是一个很好的特性。终于,我们能够很容易地测量出,查询返回的数据量和花费的时间了。

了解更多

PostgreSQL 优化