4

RPostgreSQL をWindows x64 でコンパイルして実行することができなかったため、最近 RODBC を使用して PostgreSQL に接続し始めました。読み取りパフォーマンスは 2 つのパッケージ間で類似していることがわかりましたが、書き込みパフォーマンスはそうではありません。たとえば、RODBC を使用する場合 (z は ~6.1M 行のデータフレーム):

library(RODBC)
con <- odbcConnect("PostgreSQL84")

#autoCommit=FALSE seems to speed things up
odbcSetAutoCommit(con, autoCommit = FALSE)
system.time(sqlSave(con, z, "ERASE111", fast = TRUE))

user  system elapsed
275.34  369.86 1979.59 

odbcEndTran(con, commit = TRUE)
odbcCloseAll()

一方、RPostgreSQL (32 ビット未満) を使用した同じ ~6.1M 行のデータフレームの場合:

library(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname="gisdb", user="postgres", password="...")
system.time(dbWriteTable(con, "ERASE222", z))

user  system elapsed 
467.57   56.62  668.29 

dbDisconnect(con)

したがって、このテストでは、RPostgreSQL はテーブルの書き込みにおいて RODBC の約 3 倍の速さです。このパフォーマンス比は、データフレーム内の行数に関係なく、ほぼ一定に保たれているようです (ただし、列数の影響ははるかに少なくなります)。COPY <table> FROM STDINRODBC が一連のクエリを発行している間、RPostgreSQLは次のようなものを使用していることに気付きましたINSERT INTO <table> (columns...) VALUES (...)。また、RODBC は整数に int8 を選択しているように見えますが、RPostgreSQL は必要に応じて int4 を選択しているようです。

この種のデータフレームのコピーを頻繁に行う必要があるため、RODBC の高速化に関するアドバイスをいただければ幸いです。たとえば、これは ODBC に固有のものですか、それとも正しく呼び出していませんか?

4

1 に答える 1

1

これに対する即時の回答はないようです。

Sharpie は正しくCOPY FROM、データを Postgres に取り込む最も速い方法です。彼の提案に基づいて、パフォーマンスを大幅に向上させる関数をハックしましたRODBC::sqlSave()。たとえば、110 万行 (24 列) のデータフレームを書き込むにはsqlSave、以下の関数を使用すると 69 秒に対し、960 秒 (経過) かかりました。データは一度ディスクに書き込まれ、次に再びデータベースに書き込まれるため、これは予想していませんでした。

library(RODBC)
con <- odbcConnect("PostgreSQL90")

#create the table
createTab <- function(dat, datname) {

  #make an empty table, saving the trouble of making it by hand
  res <- sqlSave(con, dat[1, ], datname)
  res <- sqlQuery(con, paste("TRUNCATE TABLE",datname))

  #write the dataframe
  outfile = paste(datname, ".csv", sep = "")
  write.csv(dat, outfile)
  gc()   # don't know why, but memory is 
         # not released after writing large csv?

  # now copy the data into the table.  If this doesn't work,
  # be sure that postgres has read permissions for the path
  sqlQuery(con,  
  paste("COPY ", datname, " FROM '", 
    getwd(), "/", datname, 
    ".csv' WITH NULL AS 'NA' DELIMITER ',' CSV HEADER;", 
    sep=""))

  unlink(outfile)
}

odbcClose(con)
于 2011-04-22T14:20:38.530 に答える