Параллелизация SQL-запросов в R
У меня есть шесть SQL-запросов, которые я script, хотя R каждый занимает очень много времени (~ 30 минут каждый). Когда каждый запрос возвращается, я затем обрабатываю данные для некоторых стандартных отчетов.
Что я хотел бы сделать, так это использовать мою многоядерную машину для параллельного запуска этих SQL-запросов из R.
Я нахожусь на Windows-машине с Oracle DB. Я следил за сообщением , чтобы использовать doSNOW и foreach, чтобы попытаться разбить эти запросы, и это лучшее, что я могу найти на qaru.site/info/372412/....
Мне удалось заставить этот процесс работать для непараллельной% do% версии foreach, но не для% dopar%. С% dopar% он просто возвращает пустой набор. Ниже приведен код, который устанавливает таблицы и запускает запросы, чтобы вы могли видеть, что происходит. Извините заранее, если есть слишком много базового кода.
Я просмотрел некоторые другие R-пакеты, но не видел очевидного решения. Также, если у вас есть лучший способ управлять этим процессом, мне было бы интересно его услышать - просто имейте в виду, что я аналитик, а не ученый-компьютер. Спасибо!
#Creating a cluster
library(doSNOW)
cl <- makeCluster(c("localhost","localhost"), type = "SOCK")
registerDoSNOW(cl)
#Connecting to database through RODBC
ch=odbcConnect("",pwd = "xxxxx", believeNRows=FALSE)
#Test connection
odbcGetInfo(ch)
#Creating database tables for example purposes
qryA1 <- "create table temptable(test int)"
qryA2 <- "insert into temptable(test) values((1))"
qryA3 <- "select * from temptable"
qryA4 <- "drop table temptable"
qryB1 <- "create table temptable2(test int)"
qryB2 <- "insert into temptable2(test) values((2))"
qryB3 <- "select * from temptable2"
qryB4 <- "drop table temptable2"
sqlQuery(ch, qryA1)
sqlQuery(ch, qryA2)
doesItWork <- sqlQuery(ch, qryA3)
doesItWork
sqlQuery(ch, qryB1)
sqlQuery(ch, qryB2)
doesItWork <- sqlQuery(ch, qryB3)
doesItWork
result = c()
output = c()
databases <- list('temptable','temptable2')
#Non-parallel version of foreach
system.time(
foreach(i = 1:2)%do%{
result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i]))
output[i] = result
}
)
output
#Parallel version of foreach
outputPar = c()
system.time(
foreach(i = 1:2)%dopar%{
#Connecting to database through RODBC
ch=odbcConnect(dsn ,pwd = "xxxxxx", believeNRows=FALSE)
#Test connection
odbcGetInfo(ch)
result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i]))
outputPar[i] = result
}
)
outputPar
sqlQuery(ch, qryA4)
sqlQuery(ch, qryB4)
Ответы
Ответ 1
Когда вы выполняете назначение outputPar[i] = result
внутри цикла последовательного цикла foreach, это нормально (но на самом деле не предназначено для использования foreach). Когда вы выполняете это задание в параллельном цикле, это не нормально. См. http://tolstoy.newcastle.edu.au/R/e10/help/10/04/3237.html для аналогичного вопроса, на который ответил Дэвид Смит при революции.
В качестве решения,
system.time(
outputPar <- foreach(i = 1:2, .packages="RODBC")%dopar%{
#Connecting to database through RODBC
ch=odbcConnect(dsn ,pwd = "xxxxxx", believeNRows=FALSE)
#Test connection
odbcGetInfo(ch)
result<-sqlQuery(ch,paste('SELECT * FROM ',databases[i]))
result
}
)