2011-04-18 69 views
4

我最近開始使用RODBC連接到PostgreSQL作爲I couldn't get RPostgreSQL to compile and run in Windows x64。我發現這兩個軟件包的讀取性能是相似的,但寫入性能不是。例如,使用RODBC(其中z是一〜6.1M行數據幀):改進RODBC-Postgres的寫入性能

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同一〜6.1M行數據幀(在32位):

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倍。無論數據幀中的行數是多少(但列數的影響要小得多),此性能比似乎保持或多或少不變。我注意到RPostgreSQL使用類似COPY <table> FROM STDIN的東西,而RODBC發出一堆INSERT INTO <table> (columns...) VALUES (...)查詢。我還注意到RODBC似乎選擇int8作爲整數,而RPostgreSQL在適當的情況下選擇int4。

我需要經常做這種數據幀拷貝,所以我會非常真誠感謝任何有關加速RODBC的建議。例如,這是ODBC固有的,還是我沒有正確調用它?

+0

在我有限的經驗中,將大量數據填充到Postgres中,從'INSERT INTO'切換到'COPY'是可接受性能的必要條件。 – Sharpie 2011-04-19 03:53:32

回答

1

看起來沒有即時的答案,所以我會發佈一個kludgy解決方法,以防萬一它對任何人都有幫助。

夏普是正確的 - COPY FROM是迄今爲止最快的方式獲取數據到Postgres。根據他的建議,我一起砍了一個功能,使其性能比RODBC::sqlSave()顯着提升。例如,使用下面的函數,通過sqlSave寫入一個110萬行(通過24列)的數據幀需要960秒(經過),而使用下面的函數需要69秒。我不會預料到這一點,因爲數據一次寫入磁盤,然後再寫入數據庫。

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) 
+0

不知道您是否可以打開連接,然後將csv文件寫入它,以避免額外寫入... – 2014-04-02 23:45:20