2012-03-29 16 views
14

Mam sześć zapytań SQL, które piszę R, z których każda zajmuje bardzo dużo czasu (~ 30 minut każda). Po każdym zwróceniu zapytania manipuluję danymi w przypadku niektórych standardowych raportów.Paralelizacja zapytań SQL w R

Co chciałbym zrobić, to używać maszyny wielordzeniowe, aby uruchomić te żądania SQL równolegle z R.

jestem na komputerze z systemem Windows z Oracle DB. Śledziłem numer blog post, aby użyć instrukcji doSNOW i foreach, aby spróbować podzielić te żądania i jest to najlepsza rzecz, jaką mogę znaleźć na stronie stackoverflow.

Udało mi się przekonwertować proces na wersję niepowiązaną% do% foreach, ale nie na% dopar%. Z% dopar% po prostu zwraca pusty zestaw. Poniżej znajduje się kod, który konfiguruje tabele i uruchamia kwerendy, dzięki czemu można zobaczyć, co się dzieje. Z góry przepraszam, jeśli jest za dużo podstawowego kodu.

Sprawdziłem niektóre z innych pakietów R, ale nie widziałem oczywistego rozwiązania. Także, jeśli masz lepszy sposób zarządzania tego rodzaju procesem, byłbym zainteresowany usłyszeniem go - pamiętaj, że jestem analitykiem, a nie naukowcem komputerowym. Dzięki!

#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) 
+2

wysyłania zapytania do bazy danych w układzie równoległym tylko, aby proces wolniej, zależnie od tego, co jest przyczyną butelki. Czy jesteś pewien, że wąskim gardłem jest instancja R działająca na twoim komputerze (nie baza danych, połączenie sieciowe, komputer, na którym działa baza danych itp.)? –

+0

Czy pakiet "RODBC' jest załadowany do węzłów klastra? Jeśli nie, dodaj '.packages =" RODBC "' do swojego wywołania 'foreach()'. – BenBarnes

+0

@Joshua Ulrich - Baza danych jest dość solidna, ponieważ jest komercyjną instalacją Oracle. Kwerendy po prostu łączą się z kilkoma tabelami wymagającymi dużego przetwarzania w bazie danych. Ręczny sposób, który przyspieszyłbym, to zainicjowanie kilku wystąpień od programisty SQL, ale skrypt R wykonuje dla mnie wiele przetwarzania zapytań, więc wolałbym, aby R inicjował wiele zapytań naraz, tak aby najdłużej trzeba czekać, to długi czas zapytania zamiast dodawania wszystkich czasów zapytania razem. –

Odpowiedz

9

Po dokonaniu przypisanie outputPar[i] = result wewnątrz szeregowej pętli foreach, to jest OK (ale naprawdę nie zamierzone wykorzystanie foreach). Kiedy wykonujesz to zadanie w pętli równoległej, nie jest to w porządku. Zobacz http://tolstoy.newcastle.edu.au/R/e10/help/10/04/3237.html, aby uzyskać podobne pytanie, na które odpowiedział David Smith w Revolution.

Jako rozwiązanie

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 
} 
) 
+1

Bardzo ładne - zmodyfikowałem kod% dopol tak jak to i zadziałało. Dzięki za wszystkich pomocników. 'system.time ( test <- foreach (i = 1: 2, .packages =" RODBC ")% dopar% { # Łączenie z bazą danych za pomocą RODBC ch = odbcConnect (dsn, pwd =" xxxxxxx ", believeNRows = FAŁSZ) # # # test połączenia odbcGetInfo (CH) sqlquery (CH, pasty ("SELECT * Z, bazy danych [j])) } ) test' –

Powiązane problemy