我对SELECT ... INTO查询实际上将处理多少行(例如,我知道将实现多少行)有一个相当不错的想法。有没有一种方法(深入日志,系统表或其他方式),可以找出有多少行已被泵送到目标表中或已被SELECT查询读取?

#1 楼

正如DanielVérité提到的那样,似乎没有通用的解决方案。从文件将数据加载到表中时,可以使用以下技术来获取加载进度。

COPY命令控制台进度条

创建空表。

CREATE TABLE mytest (n int);


创建一个具有1000万行的数据文件以加载到表中。文件放入表格中并显示进度条。 />
通过使用复制命令STDIN选项,我们可以从另一个进程中输入用于复制操作的数据。 pv命令将输出一个文件并跟踪它的进度,显示进度条,ETA,总时间和数据传输速率。

COPY命令图形进度条

使用相同的常规技术,我们可以在图形应用程序或基于Web的应用程序中显示进度条。例如,使用python的psycopg2模块,您可以使用所选的文件对象调用copy命令。然后,您可以跟踪已读取了多少文件对象并显示进度条。

评论


我以前没有遇到过pv命令,并且默认情况下它没有安装在我的Debian服务器上,但是它在仓库中。描述说:“可以将pv(管道查看器)插入两个进程之间的任何常规管道中,以直观方式指示数据通过的速度”。一个非常有用的命令!

–理查德·特纳(Richard Turner)
16年1月22日在9:45

#2 楼

似乎没有通用的,受支持的方法,但是在有限的上下文中可以使用一些技巧来评估单个查询的进度。这是其中的一些。

序列

当SELECT或UPDATE查询包含任何nextval(sequence_name)或INSERT的目标列默认为nextval时,当前序列值可以在另一个会话中使用SELECT sequence_name.last_value反复查询。之所以有效,是因为序列不受事务限制。当执行计划使得该序列在查询过程中线性增加时,它可以用作进度指示器。直接浏览数据页面。似乎将元组插入到空表中但尚未提交时,它们就从dead_tuple_count函数的pgstattuple字段中计数。

演示版9.1:创建一个空表

CREATE TABLE tt AS (n numeric);


让我们在其中插入10M行: br />
在另一个会话中,在插入期间每秒检查pgstattuple:

INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);


结果:

$ while true;
   do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
   sleep 1;
  done


插入完成后,它回落到0(所有元组都可见并处于活动状态)。 dead_tuple_count可能具有非零值,并且如果正在进行其他写入活动(例如autovacuum)(可能是不确定不确定autovacuum的并发级别),它也可能同时更改。如果表是由语句本身创建的(CREATE TABLE ... AS SELECTSELECT * INTO newtable),则不能使用该表,因为创建是事务处理的。解决方法是创建没有行的表(添加LIMIT 0)并在下一个事务中填充它。

请注意,pgstattuple并非免费提供:它在每次调用时都会扫描整个表。同样,它也仅限于超级用户。您必须以某种方式将函数与查询结合起来,以使执行程序调用它。通知是在查询期间发送的,它们不需要单独的会话,只需一个SQL客户端即可显示它们(psql是明显的候选者)。

重新制作了INSERT INTO示例以发出通知:

0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0




有关函数的堆栈溢出的相关问题:如何从长期运行的PostgreSQL函数到客户端的进度报告

未来的选择?

截至2017年5月,已经向开发者社区提交了一个很有希望的补丁:可能会最终成为PostgreSQL 11或更高版本中的通用解决方案。 br />

#3 楼

在@@ AmirAliAkbari在回答中提到的进度报告功能不会得到扩展之前,这是一种操作系统级的解决方法。

这仅适用于Linuxes,但很可能存在适用于Google的类似解决方案

PostgreSQL的最大优点和缺点是,它的所有后端都是简单的单线程进程,它们在交互时使用lseek()read()write()来操纵它们的表文件。

此结果导致其所有后端进程始终在单个查询上运行,可以很容易地找到它,并且很容易。 ,您可以从strace看到后端PID:

29805270 | dbname  | 20019 |    16384 | username  |                  |             |                 |          -1 | 2018-09-19 21:31:57.68234+02  | 2018-09-19 21:31:59.435376+02 | 2018-09-\
20 00:34:30.892382+02 | 2018-09-20 00:34:30.892386+02 | Client          | ClientRead | active              |       92778 |        92778 |  INSERT INTO ...something...


第三列是pid。在PostgreSQL中,它与后端的Linux进程pid相同。

接下来,您可以跟踪它,例如通过SELECT * FROM pg_stat_activity;进行跟踪:( strace -p 20019 -s 8192很有用,因为postgresql使用8192字节长的块) 。

sendto(10, "Cq4312078qq4312078qq4312078qINSERT 0 1q4312078qZq4312078qq4312078qq4312078qT", 22, 0, NULL, 0) = 22
recvfrom(10, "Qq4312078qq4312078q7 INSERT <removed by @peterh>", 8192, 0, NULL, NULL) = 440
sendto(10, "Cq4312078qq4312078qq4312078qINSERT 0 1q4312078qZq4312078qq4312078qq4312078qT", 22, 0, NULL, 0) = 22
lseek(298, 343634345)...
read(298, "<block data which was read in>"....
write(298, "<block data which was written out>"...


含义:如果后端对客户端进行响应,则会发生-s 8192。在该示例中,它回答了sendto查询的结果。如果后端从客户端得到某些信息,则会发生INSERT。在示例中,它通常是一个新查询,而另一个recvfrom。如果后端在表文件中切换位置,则会发生INSERT。如果后端读取a则发生lseek。从表文件中阻止。

如果后端将阻止写出到表文件中,则会发生read。表中该块的内容。它可以帮助您理解,它在做什么以及它在哪里。

对于write,您可以看到实际的查询,后端有什么。

#4 楼

正如在其他答案中所说的那样,当前一般没有直接的进度报告方法。


PostgreSQL能够在命令执行过程中报告某些命令的进度。当前,唯一支持进度报告的命令是VACUUM。



但是,从9.6开始,每当VACUUM运行时,pg_stat_progress_vacuum视图将为当前每个后端(包括自动清理工作进程)包含一行。吸尘。有关pg_stat_progress_vacuum的更多详细信息,请参见文档:27.4进度报告。

评论


在版本12中,您还可以查看CREATE INDEX的进度

– TobiasMühl
20-4-20在5:24