使用 COPY 通过 R 加速将 100 万行以上的行插入 Postgres?

Posted

技术标签:

【中文标题】使用 COPY 通过 R 加速将 100 万行以上的行插入 Postgres?【英文标题】:Speed up INSERT of 1 million+ rows into Postgres via R using COPY? 【发布时间】:2017-04-11 15:47:19 【问题描述】:

我想使用 R 向 postgreSQL 数据库批量插入/UPSERT 大量行。为此,我正在使用 R 准备一个多行 INSERT 字符串。

 query <- sprintf("BEGIN;
                         CREATE TEMPORARY TABLE 
                         md_updates(ts_key varchar, meta_data hstore) ON COMMIT DROP;

                         INSERT INTO md_updates(ts_key, meta_data) VALUES %s;
                         LOCK TABLE %s.meta_data_unlocalized IN EXCLUSIVE MODE;

                         UPDATE %s.meta_data_unlocalized
                         SET meta_data = md_updates.meta_data
                         FROM md_updates
                         WHERE md_updates.ts_key = %s.meta_data_unlocalized.ts_key;
                         COMMIT;", md_values, schema, schema, schema, schema)

DBI::dbGetQuery(con,query)

整个函数可以在here找到。令人惊讶的是(至少对我来说)我了解到 UPDATE 部分不是问题。我把它排除在外,再次运行查询,但速度并没有快多少。插入一百万多条记录似乎是这里的问题。

我做了一些研究,发现了很多信息:

bulk inserts

bulk inserts II

what causes large inserts to slow down

@Erwin Brandstetter 和@Craig Ringer 的回答特别有帮助。通过删除索引并遵循其他一些建议,我能够加快速度。

但是,我很难实施另一个听起来很有希望的建议:COPY。问题是我无法在 R 中完成它。

以下对我有用:

sql <- sprintf('CREATE TABLE 
            md_updates(ts_key varchar, meta_data hstore);
            COPY md_updates FROM STDIN;')


 dbGetQuery(sandbox,"COPY md_updates FROM 'test.csv' DELIMITER ';' CSV;")

但如果不读取额外的 .csv 文件,我将无法完成。所以我的问题是:

COPY 在这里真的是一个很有前途的方法吗(在我得到的多行 INSERT 上?

有没有办法在 R 中使用 COPY 而无需将数据写入文件。数据确实适合内存,既然它已经在内存中,为什么要写入磁盘?

我分别在 OS X 和 RHEL 上使用 PostgreSQL 9.5 和 9.5。

【问题讨论】:

它必须在 R 中吗? R可以拨打psql吗?如果是这样,请使用\COPY(不是COPY @Neil McGuigan 是的,一定是 R。R 可以进行任何类型的系统调用,所以 psql 是一个选项,但因为这是一个包的一部分并部署到我不想依赖的任何地方在 psql 上。仍在寻找内部 R 解决方案。 请让 Erwin 从 Eric 那里回来——看起来很奇怪 ***.com/a/24289817/5315974 ?.. 抱歉,已编辑名称。得怪自动更正。当然还有我。 【参考方案1】:

RPostgreSQL 有一个“CopyInDataframe”函数,看起来它应该做你想做的事:

install.packages("RPostgreSQL")
library(RPostgreSQL)
con <- dbConnect(PostgreSQL(), user="...", password="...", dbname="...", host="...")
dbSendQuery(con, "copy foo from stdin")
postgresqlCopyInDataframe(con, df)

其中表foo与数据框df具有相同的列

【讨论】:

感谢 +1 这确实有效。我多年来一直使用RPostgreSQL 包,但没有搜索过这样的功能。它正是我想要的。将运行几个基准测试,看看它是否真的加快了速度。 感谢您的帮助。对于较大的INSERTs,它实际上快了 6 倍。 这个链接似乎对在 postgres 表上附加更多记录也很有帮助 - ***.com/questions/33634713/…

以上是关于使用 COPY 通过 R 加速将 100 万行以上的行插入 Postgres?的主要内容,如果未能解决你的问题,请参考以下文章

为 40 个数据帧加速 pandas concat 函数,每个数据帧有 100 万行和 100 列

前端加载超大图片(100M以上)实现秒开解决方案

通过 JDBC 在 Oracle 中 SELECT 和 UPDATE 100 万行的性能不佳

记录--前端加载超大图片(100M以上)实现秒开解决方案

加速处理 500 万行坐标数据

我可以将超过 100 万行的 SQL 结果复制并粘贴到 Excel 中吗?