为什么PostgreSQL在多次插入过程中使用的内存比复制多?

lqfhib0f  于 2023-04-29  发布在  PostgreSQL
关注(0)|答案(1)|浏览(159)

我一直在使用Laurenz Albe的博客https://www.cybertec-postgresql.com/en/postgresql-bulk-loading-huge-amounts-of-data/练习批量加载。当我稍微改变它的时候,问题就开始了。表是一样的:

CREATE TABLE t_sample
(
     a              varchar(50),
     b              int,
     c              varchar(50),
     d              int
);

而不是

BEGIN;
INSERT INTO t_sample VALUES ('abcd', 1, 'abcd', 1);
INSERT INTO t_sample VALUES ('abcd', 1, 'abcd', 1);
INSERT INTO t_sample VALUES ('abcd', 1, 'abcd', 1);
…
COMMIT;`

我用

BEGIN;
INSERT INTO t_sample VALUES
('abcd', 1, 'abcd', 1),
('abcd', 1, 'abcd', 1),
('abcd', 1, 'abcd', 1),
…
COMMIT;

对于那些不想读博客的人:我尝试比较COPY和insert方法之间的内存消耗。
此外,我使用了2097152条记录而不是100万条记录。我将这些命令保存为一个文件 multipleinsert。SQL 并像psql -d load_test -f multipleinsert.sql一样运行它。
另外,正如在博客中所述,我使用了COPY方法,如下所示(当然,记录数相同,2097152)

COPY t_sample FROM stdin;
abcd 1 abcd 1
abcd 1 abcd 1
abcd 1 abcd 1
...

插入14的执行时间。543 s,COPY为1。237.然而,这不是我想比较的重点。当我使用COPY时,服务器上的可用内存几乎没有减少,但在执行insert语句期间,可用内存减少了近6,5 GB。包含insert语句本身的文件将近49 MB,所以PostgreSQL尝试缓存它,但为什么它会扩展到~6,5GB?是否有一种计算方法来(粗略地)计算PostgreSQL在这样的加载中所消耗的内存?
注意:How does COPY work and why is it so much faster than INSERT?,很好地说明了为什么COPY比insert快,但这篇文章和互联网上的任何其他文章都没有说明内存消耗。

5vf7fwbs

5vf7fwbs1#

多行INSERT的处理方式与COPY不同。

  • 使用INSERT,从客户端发送一个大型语句,在服务器上进行解析和计划,然后执行。整个语句保存在客户端和服务器上的内存中,整个大的事情必须被解析和规划,所以如果这会占用大量内存,我并不感到惊讶。

但是,我无法解释为什么一个50MB的语句会暂时需要6。5 GB内存,这似乎太多了。

  • COPY语句本身很小,数据从客户端流到服务器,并在到达时插入到表中。为了提高性能,COPY可以批量插入多行数据,但是批量数据小于200万行数据,因此使用的内存更少。

要调试为什么要使用这么多内存,请在机器上禁用内存过度使用,然后让INSERT运行,直到内存不足。PostgreSQL将向日志文件写入内存上下文转储,它将告诉您内存分配的位置。

相关问题