使用dplyr或pool并行处理和查询SQL:MySQL服务器已经消失
前面有几个相关问题,但没有一个能解决我的问题:使用dplyr或pool并行处理和查询SQL:MySQL服务器已经消失,mysql,r,parallel-processing,Mysql,R,Parallel Processing,前面有几个相关问题,但没有一个能解决我的问题: 我的用例如下:我有一个需要打印的数据的大数据库。由于对数据和绘图本身进行了一些必要的预处理(ggplot2),每个绘图都需要几秒钟的时间来创建。我需要做大量的绘图。我的想法是,我将通过dplyr连接到数据库,而无需将所有数据下载到内存中。然后我有一个函数,它获取要绘制的数据子集。这种方法在使用单线程时效果很好,但是当我尝试使用并行处理时,我遇到了与连接相关的SQL错误MySQL服务器已经消失了 现在,在这种情况下,解决方案只是终止函数中的
MySQL服务器已经消失了
现在,在这种情况下,解决方案只是终止函数中的当前连接,这迫使建立一个新连接。我是用connection.close()
实现的,其中connection
来自Django的Django.db
我的问题是,我找不到这种方法的R等价物。当我找到R的包时,我认为我已经找到了解决方案:
此包支持为各种类型的对象创建对象池
对象,以降低获取对象的计算成本。
目前唯一受支持的池对象是DBI
连接(请参阅
DBI
程序包以获取更多信息),可用于查询数据库
直接通过DBI
或通过dplyr
。但是,池
类
通用性足以允许任何R对象的池,前提是
有人适当地实现了后端(创建对象
工厂类和所有必需的方法)--带有
有关如何操作的说明将很快发布
我的代码太大,无法在此处发布,但本质上是这样的:
#libraries loaded as necessary
#connect to the db in some kind of way
#with dplyr
db = src_mysql(db_database, username = db_username, password = db_password)
#with RMySQL directly
db = dbConnect(RMySQL::MySQL(), dbname = db_database, username = db_username, password = db_password)
#with pool
db = pool::dbPool(RMySQL::MySQL(),
dbname = db_database,
username = db_username,
password = db_password,
minSize = 4)
#I tried all 3
#connect to a table
some_large_table = tbl(db, 'table')
#define the function
some_function = function(some_id) {
#fetch data from table
subtable = some_large_table %>% filter(id == some_id) %>% collect()
#do something with the data
something(subtable)
}
#parallel process
mclapply(vector_of_ids,
FUN = some_function,
mc.cores = num_of_threads)
上面的代码与Python代码不同,这就是关键区别。您在Python中所做的一切在R中是完全可能的(请参见下面的MWE)。但是,您上面的代码不是: 终止函数中的当前连接,从而强制建立新连接 它尝试(但失败)的是使数据库连接从父进程传输到调用
mclappy
打开的每个子进程。这是不可能的。无论发生什么情况,数据库连接都不能跨越进程边界
这是一个更一般的“规则”的示例,即子进程不能影响父进程的状态period。例如,子进程也不能写入内存位置。您也不能从这些子进程打印(到父进程的图形设备)
为了执行与Python中相同的操作,如果希望函数真正并行,则需要在函数FUN
(mclappy的第二个参数)内部打开一个新连接。也就是说,您必须确保dbConnect
调用发生在子进程内部
这消除了池
(尽管使用起来非常安全),因为池
在重用连接时非常有用,并且通常希望它们易于访问。对于您的并行用例,由于您不能跨越流程边界,这是无用的:您将始终需要打开和关闭每个新流程的连接,因此您最好完全跳过池
以下是Python解决方案到R的正确“翻译”:
library(dplyr)
getById <- function(id) {
# create a connection and close it on exit
conn <- DBI::dbConnect(
drv = RMySQL::MySQL(),
dbname = "shinydemo",
host = "shiny-demo.csa7qlmguqrf.us-east-1.rds.amazonaws.com",
username = "guest",
password = "guest"
)
on.exit(DBI::dbDisconnect(conn))
# get a specific row based on ID
conn %>% tbl("City") %>% filter(ID == id) %>% collect()
}
parallel::mclapply(1:10, getById, mc.cores = 12)
库(dplyr)
getById%筛选器(ID==ID)%%>%collect()
}
并行::mclapply(1:10,getById,mc.cores=12)