2012-05-15 16 views
6

Realizo muchas consultas SQL a una base de datos de la industria muy lejos, pero lleva mucho tiempo recibir los resultados. Fue mucho más rápido cuando mi computadora con R estaba casi al lado de la base de datos, lo que me lleva a pensar que es la latencia entre mi computadora y la base de datos el cuello de botella, y que ejecutar consultas paralelas puede acelerar las cosas. Estamos en diferentes continentesParallel for-loop en Windows

Aquí está una versión de trabajo que no está en paralelo:

doQueries <- function(filenameX, inp1, inp2) { 
    print(paste("Starting:", inp1, inp2, ",saving to", filenameX, sep=" ")) 
    # Here should the query be (using RODBC) 
    # save(queryresults, file="filenameX") 
} 

input.rows <- cbind(c("file1.rda","file2.rda","file3.rda"),c("A","B","C"),c(12,13,14)) 

for (i in 1:nrow(input.rows)) { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

He tratado con el siguiente código, pero el foreach-biblioteca no parecen estar disponible y como yo entiendo de la lectura en CRAN, paralelo está reemplazando paquetes anteriores por paralelo ("paquete 'foreach' no está disponible (para R versión 2.15.0)").

library(parallel) 
library(foreach) 
foreach (i=1:nrow(input.rows)) %dopar% { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

¿Cómo debo hacer esto?

¡Gracias a todos los colaboradores de Stackoverflow!

/Chris

Actualización: Gracias a nograpes, me las arreglé para cargar las bibliotecas. El siguiente código parece funcionar:

library(RODBC) 
library(doParallel) 
library(foreach) 

# odbcCloseAll() 
# my_conn <- odbcConnect("database", uid="xx", pwd="yy", case="nochange") 

doQueries <- function(filenameX, inp1, inp2) { 
    print(paste("Starting:", inp1, inp2, ",saving to", filenameX, sep=" ")) 
    # sql.test <- RODBC::sqlQuery(my_conn, "SELECT * FROM zzz LIMIT 100", rows_at_time=1024) 
    # save(sql.test, file="filenameX") 
} 

input.rows <- cbind(c("file1.rda","file2.rda","file3.rda"),c("A","B","C"),c(12,13,14)) 

cl <- makeCluster(3) 
registerDoParallel(cl) 

foreach (i=1:nrow(input.rows)) %dopar% { 
    doQueries(filenameX=input.rows[i,1], inp1=input.rows[i,2], inp2=input.rows[i,3]) 
} 

stopCluster(cl) 

Pero cuando incluyo el SQL-consulta real, aparece este mensaje-error: Error en {: tarea 1 falló - "primer argumento no es un canal RODBC abierta"

¿Podría ser para que esto no funcione conceptualmente? ¿Que RODBC no puede manejar más de una consulta a la vez?

Realmente aprecio todo el apoyo.

/Chris

Actualización 2: Muchas gracias por las respuestas nograpes muy buenas e impresionantes. Es difícil juzgar si las transferencias de datos son más rápidas (creo que el rendimiento total es un 20% más rápido), pero encontré que las consultas (alrededor de 100) tienen diferentes tiempos de respuesta y necesitan un postprocesamiento (que incluyo en la función antes de guardar), obtengo una mejor utilización del enlace y la CPU local. Es decir. con solo una consulta en ese momento, las CPU casi no se utilizarán durante la transferencia de datos, y luego el enlace permanecerá en silencio mientras las CPU funcionen. Con consultas paralelas, veo que llegan datos y que las CPU funcionan al mismo tiempo. En total, se volvió mucho más rápido. ¡Muchas gracias!

/Chris

+0

Si el cuello de botella es la conexión de red entre su computadora y la base de datos, una consulta paralela no será más rápida. Las consultas SQL se ejecutarán simultáneamente en la base de datos (que puede ser un poco más rápido, pero tal vez no), y luego se enviarán a su computadora. El envío a la parte de su computadora será la parte lenta, la cual no cambia en absoluto paralelizándola. – nograpes

Respuesta

7

Como ya he mencionado en mi comentario, esta técnica probablemente no será más rápido. Para responder a su pregunta, el paquete foreach está disponible para su versión de R. Quizás su repositorio seleccionado no se haya actualizado aún. Pruebe esto:

install.packages('foreach', repos='http://cran.us.r-project.org') 

que debería instalar el paquete. Si eso no funciona, tome el archivo binario para su OS here, y simplemente instálelo a través de los menús.

Si el cuello de botella es la conexión de red, solo puede acelerar el proceso reduciendo la cantidad de material que coloca en la red. Una idea sería conectarse remotamente al servidor de la base de datos, hacer que descargue la consulta a un archivo (en el servidor), comprimirlo y luego descargarlo a su computadora, luego hacer que R descomprima y lo cargue.Suena como mucho, pero es probable que pueda hacer todo el proceso dentro de R.

el seguimiento de su actualización, parece que usted no incluyó un argumento .packages en su estado de cuenta foreach. Esta es la razón por la cual usted tuvo que prefijar la función sqlQuery con RODBC::. Es necesario especificar qué paquetes necesita el ciclo, porque creo que esencialmente inicia una nueva sesión R para cada nodo, y cada sesión debe inicializarse con los paquetes. Del mismo modo, no puede acceder al my_conn porque estaba fuera del bucle, debe crear dentro del bucle para que cada nodo tenga su propia copia.

library(RODBC) 
library(foreach) 
library(doParallel) 
setwd('C:/Users/x/Desktop') 

doQueries <- function(filenameX) { 
    sql.text<-sqlQuery(my_conn, 'SELECT * FROM table;') 
    save(sql.text, file=filenameX) 
} 

cl <- makeCluster(2) 
registerDoParallel(cl) 

foreach (i=1:2, .packages='RODBC') %dopar% { 
    my_conn <- odbcConnect("db", uid="user", pwd="pass") 
    doQueries(filenameX=paste('file_',i,sep='')) 
} 

Pero, como he mencionado, esto probablemente no será más rápido.

+0

Avíseme si fue más rápido. – nograpes

+0

Sí, me sorprendió ver una mejor utilización total, consulte mi "actualización 2" más arriba. ¡Muchas gracias! – Chris

Cuestiones relacionadas