七月 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=300000 和 width=107,也就是大约 30MB。
但是,序列化时显示了全量输出为 output=2348329kB,也就是 2.24GB!这比原来超出了 76 倍。
对于任何从事查询优化的人来说,这都是一个很好的特性。终于,我们能够很容易地测量出,查询返回的数据量和花费的时间了。