在PostgreSQL中进行监控时,从9.6和pg_stat_process_vacuum(针对于VACUUM
)开始,就出现了能够给出时间点操作状态的进度报告。自本次提交起,PostgreSQL 14在这一领域添加了一项新功能,用于COPY
的进度报告
commit: 8a4f618e7ae3cb11b0b37d0f06f05c8ff905833f
author: Tomas Vondra <tomas.vondra@postgresql.org>
date: Wed, 6 Jan 2021 21:46:26 +0100
Report progress of COPY commands
This commit introduces a view pg_stat_progress_copy, reporting progress
of COPY commands. This allows rough estimates how far a running COPY
progressed, with the caveat that the total number of bytes may not be
available in some cases (e.g. when the input comes from the client).
Author: Josef Šimánek
Reviewed-by: Fujii Masao, Bharath Rupireddy, Vignesh C, Matthias van de Meent
Discussion: https://postgr.es/m/CAFp7QwqMGEi4OyyaLEK9DR0+E+oK3UtA4bEjDVCa4bNkwUY2PQ@mail.gmail.com
Discussion: https://postgr.es/m/CAFp7Qwr6_FmRM6pCO0x_a0mymOfX_Gg+FEKet4XaTGSW=LitKQ@mail.gmail.com复制
这是该功能的初始提交,在第二次提交中得到了改进,可以获得更多信息。
根据数据量的不同,COPY
可能运行时间很长,以至于用户无法知道COPY
运行的进度与状态。现在可以在名为pg_stat_progress_copy 的系统视图中跟踪操作状态,该视图为每个后台运行的COPY
返回一行。跟踪了以下几个字段:
运行该操作的后端PID
操作类型:COPY FROM, TO
对关系进行操作,如果使用
SELECT with COPY FROM
,则为 0。处理的数据量,来源于每次处理元组时聚合的行的大小
COPY FROM
中指定WHERE
子句。显示被处理,甚至跳过的元组数。COPY FROM
原始文件中的数据总量。如果数据是通过stdin
或psql
的\copy
这样的管道提供的,则没有这部分数据,因为后端直接在数据文件上使用stat(),因此只能从位于与PostgreSQL实例运行的同一主机中的文件进行COPY FROM
。
让我们举一个简单的例子,首先是COPY TO
:
=# CREATE TABLE copy_tab (a int, b text);
CREATE TABLE
=# INSERT INTO copy_tab SELECT generate_series(1, 10) AS a,
'a' || generate_series(1, 10) AS b;
INSERT 0 10
=# COPY copy_tab TO '/tmp/copy_tab_data.txt';
COPY 10
复制
接近操作结束时,报告看起来是这样的,所有行都已处理,数据总量如下:
=# SELECT relid::regclass, command, type, bytes_processed, tuples_processed
FROM pg_stat_progress_copy;
relid | command | type | bytes_processed | tuples_processed
----------+---------+------+-----------------+------------------
copy_tab | COPY TO | FILE | 52 | 10
(1 row)
复制
下面是一个COPY FROM
的示例,其中排除了一半行:
=# TRUNCATE copy_tab ;
TRUNCATE TABLE
=# COPY copy_tab FROM '/tmp/copy_tab_data.txt' WHERE a > 5;
COPY 5
复制
接近操作结束时,报告看起来是这样的,详细说明了处理的元组数和WHERE
筛选排除的元组数:
=# SELECT relid::regclass, command,
type, bytes_processed, bytes_total,
tuples_processed, tuples_excluded FROM pg_stat_progress_copy;
relid | command | type | bytes_processed | bytes_total | tuples_processed | tuples_excluded
----------+-----------+------+-----------------+-------------+------------------+-----------------
copy_tab | COPY FROM | FILE | 52 | 52 | 5 | 5
(1 row)
复制
如上所述,通过管道发送数据不会给出预期要处理的字节总数的信息:
=# \copy copy_tab FROM '/tmp/copy_tab_data.txt' WHERE a > 5;
COPY 5
复制
请注意type
的更改,bytes_total
报告0
:
=# SELECT relid::regclass, command,
type, bytes_processed, bytes_total,
tuples_processed, tuples_excluded FROM pg_stat_progress_copy;
relid | command | type | bytes_processed | bytes_total | tuples_processed | tuples_excluded
----------+-----------+------+-----------------+-------------+------------------+-----------------
copy_tab | COPY FROM | PIPE | 52 | 0 | 5 | 5
(1 row)
复制
正如任何现有的进度报告一样,这仅提供有关查看目录时操作状态的信息,但是可以轻松地为操作进行时间估计,例如使用简单的 \watch
命令和 INSERT SELECT into
存储目录数据的自定义表或执行此工作的外部模块,这需要一些额外的努力。