每次在 MySQL DB 中加载 R 输出

Posted

技术标签:

【中文标题】每次在 MySQL DB 中加载 R 输出【英文标题】:Load the R output eachtime in MySQL DB 【发布时间】:2014-03-21 02:17:36 【问题描述】:

我有一个循环,它对数据框中的每一行进行迭代并生成 5 个输出文件 并继续为所有记录附加到同一个文件 - 代码工作正常。

for (n in 1:nrow(Data)) 
    #Initialize the required variables
   (some function ---)   

    #Write the file into the output file

    df1= data.frame (key,value)
    df2= data.frame (key,value)
    df3= data.frame (key,value)
    df4= data.frame (key,value)
    df5= data.frame (key,value)

    write.table(df1, file = paste(pradd,"table1.tsv",sep="/"), append = TRUE, quote = FALSE, sep = "\t")
    write.table(df2, file = paste(pradd,"table2.tsv",sep="/"), append = TRUE, quote = FALSE, sep = "\t")
    write.table(df3, file = paste(pradd,"table3.tsv",sep="/"), append = TRUE, quote = FALSE, sep = "\t")
    write.table(df4, file = paste(pradd,"table4.tsv",sep="/"), append = TRUE, quote = FALSE, sep = "\t")
    write.table(df5, file = paste(pradd,"table5.tsv",sep="/"), append = TRUE, quote = FALSE, sep = "\t") 

但是我想加载输出 - 直接从 R 到 mysql DB 作为五个表。 这 5 个文件很大,我必须使用库来更快地加载到 db 表中。

我正在使用RODBC 连接到 MySQL。通过建立连接,我可以将 MySQL 表读入 R。不知道如何每次加载 5 个表 - 我的 for 循环运行。

更新: 我试过下面的代码——它正在加载——但是sqlQuery很慢。我的for循环处理很快,但是当我尝试加载到数据库时它很慢。

for (i in 1: nrow(Data))

(--Some function to create dataset 1 to dataset 4 --- )

# collect the result in dataset1  and  put them in a .txt file and use the .txt file to load into db
write.table(dataset1 , file1.txt, append=False, sep = "\t")
sqlQuery(channel," LOAD DATA LOCAL INFILE 'file1.txt' INTO TABLE lta_r_db.file1  FIELDS TERMINATED BY '\t'  LINES TERMINATED BY '\\n';")

# collect the result in dataset2  and  put them in a .txt file and use the .txt file to load into db
write.table(dataset2 , file2.txt, append=False, sep = "\t")
sqlQuery(channel," LOAD DATA LOCAL INFILE 'file2.txt' INTO TABLE lta_r_db.file2  FIELDS TERMINATED BY '\t'  LINES TERMINATED BY '\\n';")

write.table(dataset3 , file3.txt, append=False, sep = "\t")
sqlQuery(channel," LOAD DATA LOCAL INFILE 'file3.txt' INTO TABLE lta_r_db.file3  FIELDS TERMINATED BY '\t'  LINES TERMINATED BY '\\n';")

write.table(dataset4 , file4.txt, append=False, sep = "\t")
sqlQuery(channel," LOAD DATA LOCAL INFILE 'file4.txt' INTO TABLE lta_r_db.file4  FIELDS TERMINATED BY '\t'  LINES TERMINATED BY '\\n';")

write.table(dataset5 , file5.txt, append=False, sep = "\t")
sqlQuery(channel," LOAD DATA LOCAL INFILE 'file5.txt' INTO TABLE lta_r_db.file5  FIELDS TERMINATED BY '\t'  LINES TERMINATED BY '\\n';")

我怎样才能在处理能力得到很大改善的情况下运行上述内容。

【问题讨论】:

【参考方案1】:

在这里,您可以找到另一种使用虚构数据的方法 .. 以下代码测试使用base::mapplyparallel::mcmapply 在带有RMySQL::dbWriteTable 的mysql 数据库中重复插入data.frame 列表

还要考虑到,一般来说,对数据库的少数访问(以及每次访问的更多数据)越好。作为替代方案,您可以尝试在 R 中将数据打包到较大的表中,然后将它们导出到 mysql。

不过mysql这边..

## mysql> show tables;                                                          
## +----------------+                                                           
## | Tables_in_test |                                                           
## +----------------+                                                           
## | table1         |                                                           
## | table2         |                                                           
## | table3         |                                                           
## | table4         |                                                           
## | table5         |                                                           
## +----------------+                                                           
## 5 rows in set (0.00 sec)                                                     

## mysql> describe table1;                                                      
## +-------+---------+------+-----+---------+-------+                           
## | Field | Type    | Null | Key | Default | Extra |                           
## +-------+---------+------+-----+---------+-------+                           
## | id    | int(11) | YES  |     | NULL    |       |                           
## | value | float   | YES  |     | NULL    |       |                           
## +-------+---------+------+-----+---------+-------+                           
## 2 rows in set (0.00 sec)        

然后

## ## ----------------------------------------------------------       
## ## A few benchmark                                                  
## ## ----------------------------------------------------------       
## Create some data                                                    
id <- 1:5
val <- rnorm(5)
## you need to have a list of data.frame, eg                           
my.df <- data.frame("id"= 1:5,
                   "value"=rnorm(5))
df.list <- split(my.df, my.df$id)
## otherwise                                                           
## df.list <- list(df1,df2,df3,df4,df5) 
tab.names <- paste("table", 1:5, sep="")                               


## number of repetitions                                               
reps <- 100

clean <- function() 
    dbSendQuery(my.con, "delete from table1")
    dbSendQuery(my.con, "delete from table2")
    dbSendQuery(my.con, "delete from table3")
    dbSendQuery(my.con, "delete from table4")
    dbSendQuery(my.con, "delete from table5")


## ## ------------------------------------------------------- 


library(RMySQL)
library(parallel)

my.con <- dbConnect(MySQL(),
                 host = "localhost",
                 dbname = "test",
                 user = "your.username",
                 password = "your.password")

clean()


system.time(
    for (i in 1:reps) 
        mapply(dbWriteTable,
               name=tab.names ,
               value = df.list,
               MoreArgs=list(conn = my.con, append = T,
                   row.names = FALSE))
    )

clean()

system.time(
    for (i in 1:reps) 
        mcmapply(dbWriteTable,
                 name=tab.names ,
                 value = df.list,
                 MoreArgs=list(conn = my.con, append = T,
                     row.names = FALSE),
                 mc.cores = 8,
                 mc.preschedule = FALSE
                 )
    )

clean()


dbDisconnect(my.con)
rm(my.con)

我没有发现使用并行化可以提高速度。 最后,至少在我的设置中,你可以使用一个简单的

mapply(dbWriteTable,
       name=paste("table", 1:5, sep="") ,
       value = df.list,
       MoreArgs=list(conn = my.con, append = T, row.names = FALSE))

我在 unix 中不经常使用 ODBC,所以我无法针对 RODBC 进行测试,但是 HTH。

干杯

【讨论】:

【参考方案2】:

确保您的 data.frame 与数据库中的表具有相同数量的变量和相同的变量名称。

#your connection to the MySQL database
library(RODBC)
channel <- odbcConnect()
for (n in 1:nrow(Data))
    #Initialize the required variables
   (some function ---)   

    #Write the file into the output file

    df1= data.frame (key,value)

    sqlSave(channel = channel, dat = df1, tablename = "table1", append = TRUE)

odbcClose(channel)

【讨论】:

它可以工作,但是 sqlSave 很慢,如何在向其中插入更多记录时运行得更快 df1 有多少行?只有一个? sqlSave() 可以同时保存多条记录。但这可能需要您重写一些代码。看一下 ?sqlQuery() ,它允许在数据库上应用任何 SQL 命令。 我已根据建议更新了问题。我试过sqlQuery(channel,"BULK INSERT dbname.tablename FROM 'C:/Users/xx/Desktop/xx/Temp/xx/Fc/df1.txt' WITH ( FIELDTERMINATOR = ',',ROWTERMINATOR = '\\n' )") 但是我得到了 Errro:Couldnot SQL:ExecDirect 我根据您的建议更新了问题。但是处理比sqlSave好10倍,但仍然运行更长时间 我已经更正了我的代码。您不需要在 sqlSave 中引用 df1。

以上是关于每次在 MySQL DB 中加载 R 输出的主要内容,如果未能解决你的问题,请参考以下文章

JQuery UI 自动完成,在 DOM 中加载所有数据,而不是从 mysql DB 中获取

在python中加载.db文件时出现“没有这样的表”错误

如何在 R 中加载大数据? [复制]

在c++中如何使每次输出的随机数不同?

如何在脚本中加载 tflite 模型?

在tableview中加载异步图像,它们在每次滚动时消失