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

问题描述 投票:0回答:1

我一直在使用 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
和插入方法之间的内存消耗。

此外,我使用了 2097152 条记录,而不是 1 m 条记录。我将此命令保存为文件 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.543s 和

COPY
的执行时间为 1.237s。然而,这不是我要比较的重点。当我使用
COPY
时,服务器上的可用内存几乎没有减少,但在执行插入语句期间,可用内存减少了近 6.5 GB。包含插入语句的文件本身将近 49 MB,因此 PostgreSQL 尝试缓存它,但为什么它扩展到 ~6,5GB?有没有一种计算方法可以(粗略地)计算 PostgreSQL 为这种加载所消耗的内存?

注意:COPY 是如何工作的,为什么它比 INSERT 快得多?,很好地说明了为什么

COPY
比 insert 快,但是这个和互联网上的任何其他帖子都没有说明内存消耗。

postgresql bulkinsert bulk-load postgresql-14 postgresql-copy
1个回答
0
投票

多行

INSERT
COPY
的处理方式不同。

  • 使用

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

    但是,我无法解释为什么 50MB 的语句会暂时需要 6.5 GB RAM。这似乎过分了。

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

要调试为什么使用了这么多内存,请在机器上禁用内存过度使用,然后让

INSERT
运行直到内存不足。 PostgreSQL 会将内存上下文转储写入日志文件,它会告诉您内存分配在哪里。

© www.soinside.com 2019 - 2024. All rights reserved.