【问题标题】:Parallel query of SQLite database in RR中SQLite数据库的并行查询
【发布时间】:2016-04-25 02:52:49
【问题描述】:

我有一个大型数据库(~100Gb),我需要从中提取每个条目, 对其进行一些比较,然后存储这些比较的结果。我试图在单个 R 会话中运行并行查询,但没有成功。我可以一次运行多个 R 会话,但我正在寻找更好的方法。这是我尝试过的:

library(RSQLite)
library(data.table)
library(foreach)
library(doMC)



#---------
# SETUP
#---------


#connect to db
db <- dbConnect(SQLite(), dbname="genes_drug_combos.sqlite")


#---------
# QUERY
#---------
# 856086 combos = 1309 * 109 * 6

registerDoMC(8)

#I would run 6 seperate R sessions (one for each i)
res_list <- foreach(i=1:6) %dopar% {

  a <- i*109-108
  b <- i*109

  pb  <- txtProgressBar(min=a, max=b, style=3)
  res <- list()

  for (j in a:b) {

    #get preds for drug combos
    statement   <- paste("SELECT * from combo_tstats WHERE rowid BETWEEN", (j*1309)-1308, "AND", j*1309)
    combo_preds <- dbGetQuery(db, statement)

    #here I do some stuff to the result returned from the query
    combo_names <- combo_preds$drug_combo
    combo_preds <- as.data.frame(t(combo_preds[,-1]))

    colnames(combo_preds)  <- combo_names

    #get top drug combos
    top_combos <- get_top_drugs(query_genes, drug_info=combo_preds, es=T)

    #update progress and store result
    setTxtProgressBar(pb, j)
    res[[ length(res)+1 ]] <- top_combos
  }
  #bind results together
  res <- rbindlist(res)
}

我没有收到任何错误,但只有一个核心启动。相比之下,如果我运行多个 R 会话,我所有的核心都会这样做。我做错了什么?

【问题讨论】:

  • 你用的是mac还是windows?你有安装 Emacs 和 ESS 吗?
  • 也许这篇文章可以帮助support.rstudio.com/hc/en-us/articles/…
  • 我正在使用 Ubuntu 和 R studio。
  • 您需要为每个并行实例创建一个连接,而不是一个跨所有内核共享的连接
  • 就是这样 - 谢谢!一般来说,是否需要为每个并行实例创建任何必需的对象/连接?

标签: foreach parallel-processing domc rsqlite


【解决方案1】:

我在与RSQLite同时访问同一个文件SQLite数据库时学到的一些东西:

1。确保每个工作人员都有自己的数据库连接。

  parallel::clusterEvalQ(cl = cl, {
    db.conn <- RSQLite::dbConnect(RSQLite::SQLite(), "./export/models.sqlite");
    RSQLite::dbClearResult(RSQLite::dbSendQuery(db.conn, "PRAGMA busy_timeout=5000;"));
  })

2。使用PRAGMA busy_timeout=5000;

默认情况下,它设置为 0,并且每次您的工作人员在数据库锁定时尝试写入数据库时​​,您最终可能会遇到“数据库已锁定”错误。之前的代码在每个工作连接中设置了这个PRAGMA。注意SELECT 操作永远不会被锁定,只有INSERT/DELETE/UPDATE

3。使用PRAGMA journal_mode=WAL;

这只需设置一次,并且默认情况下永远保持启用状态。它将向数据库添加两个(或多或少永久)文件。它将improve 并发读/写性能。阅读更多here

使用上述设置我没有遇到this 问题。

【讨论】:

  • 我仍然收到database is locked 错误。奇怪的是,它们有时会在进程运行时间少于busy_timeout 时发生(我尝试了 5 秒到 2 分钟之间的值)。有任何想法吗?我想切换到 postgresql 会摆脱这些问题。
  • 无需切换。 SQLite 出奇的快速且易于使用。检查你的提交。我有 8 个运行 100% 的进程不断访问 NTFS 分区上的数据库。例如,如果我开始从控制台中构建索引,我会看到所有 8 个进程都停止,等待数据库再次可用,这会在索引构建后立即发生。例如,当您在控制台中运行 VACUUM 时,会导致立即退出(即锁定)。
  • 我正在使用dbWriteTable,这可能会给您带来麻烦。我一直在寻找一种方法来查找数据库提交的日志,但找不到任何东西。有什么建议吗?
  • 也许是的。我总是使用纯 SQL:dbSendQuerydbGetQuery
  • @Galadude 当您切换到 dbSendQuery 时,它解决了您的问题吗?使用 dbWriteTable 时,我也会收到 database is locked 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 2021-02-19
相关资源
最近更新 更多