2017-04-11 128 views
1

我想批量INSERT/UPSERT适度大量行使用R.为了做到这一点,我准备用R.使用COPY加速将100万行的INSERT插入到Postgres中?

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) 

整个一个多行INSERT串PostgreSQL数据库功能可以找到here。令人惊讶的是(对我来说)我了解到UPDATE部分不是问题。我离开它并再次运行查询,速度并不快。插入一百万条记录似乎是这里的问题。

我做了一些研究,发现相当长的一段信息:

bulk inserts

bulk inserts II

what causes large inserts to slow down

从@Erwin Brandstetter修改和@Craig林格答案是特别有帮助。我能够通过放弃索引和其他一些建议来加快速度。

但是,我努力实施另一个听起来很有希望的建议: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无需将数据写入到文件的方法吗? 。数据不适合在内存中,因为它已经在MEM为什么写入到磁盘?

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

+0

它必须在R' R可以调用'psql'吗?如果是这样,请使用'\ COPY'(而不是'COPY') –

+0

@Neil McGuigan是的,得到R. R可以进行任何类型的系统调用,所以psql是一个选项,但是因为这是一个包的一部分,并且部署到任何地方我不想依赖psql。仍在寻找内部R解决方案。 –

+0

请让埃里克从埃里克回来 - 它看起来很奇怪 –

回答

2

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

+0

感谢+1这实际上有效。多年来我一直在使用'RPostgreSQL'包,但没有搜索这样的功能。它正是我想要的。将运行几个基准测试,看看它是否真的加快速度。 –

+1

感谢您的帮助。对于更大的INSERT,它实际上快了6倍。 –

相关问题