我一直在使用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快,但这篇文章和互联网上的任何其他文章都没有说明内存消耗。
1条答案
按热度按时间5vf7fwbs1#
多行
INSERT
的处理方式与COPY
不同。INSERT
,从客户端发送一个大型语句,在服务器上进行解析和计划,然后执行。整个语句保存在客户端和服务器上的内存中,整个大的事情必须被解析和规划,所以如果这会占用大量内存,我并不感到惊讶。但是,我无法解释为什么一个50MB的语句会暂时需要6。5 GB内存,这似乎太多了。
COPY
语句本身很小,数据从客户端流到服务器,并在到达时插入到表中。为了提高性能,COPY
可以批量插入多行数据,但是批量数据小于200万行数据,因此使用的内存更少。要调试为什么要使用这么多内存,请在机器上禁用内存过度使用,然后让
INSERT
运行,直到内存不足。PostgreSQL将向日志文件写入内存上下文转储,它将告诉您内存分配的位置。