首页 > 解决方案 > Hadley 将 dbplyr 用于较小的数据集是什么意思?

问题描述

dbplyr当我发现这个 github 问题时,我正在寻找方法来尝试测量峰值 RAM 使用率。发帖人询问如何copy_to()在不将 tbl 放入 RAM 的情况下从一个数据库复制到另一个数据库,Hadley 回答:

我认为这超出了 dbplyr 的范围;这些工具的想法是使处理更小的数据集成为可能。对于任何大的东西,您确实需要在自己的数据管道中处理它。

我最近一直在使用dbplyrwithMonetDBLite来处理一些对内存来说太大的数据集,有时copy_to()用于编写中间数据,结果大多都很好,所以我很困惑他的意思是什么,如果我我错过了一些重要的东西。

工作示例

只是为了完成一个(玩具)示例,假设我有以下 .csv 文件:

# produces ~700Mb file, in ~25 seconds (on my machine)
library(tidyverse)
mtcars %>%
  mutate(replicate = list(1:500000)) %>%
  unnest(replicate) %>%
  arrange(replicate) %>%
  write_csv("big.csv")

我想使用 dplyr 前端将所有值加 1 并保存结果以供以后处理。

对于 tibbles,以下内容似乎在大约 4.3GB RAM 使用量时达到峰值:

big.modified <- read_csv("big.csv") %>%
  mutate(across(everything(), ~ .x + 1))

使用MonetDBLite+ dbplyr,以下似乎运行良好并且使用的 RAM 量可以忽略不计:

library(DBI)
library(MonetDBLite)
con <- dbConnect(MonetDBLite::MonetDBLite(), "example.db")
# read, streaming
monetdb.read.csv(con, "big.csv", "big")

tbl(con, "big") %>%
  mutate(across(everything(), ~ .x + 1)) %>%
  copy_to(con, ., "big_modified", temporary = FALSE)

结果相同:

all.equal(as.data.frame(big.modified),
          as.data.frame(tbl(con, "big_modified") %>% collect()))
#> [1] TRUE

不像DBI::dbWriteTable(),如果在上面使用,它似乎花费了大约 1.5GB 峰值 RAM,copy_to()似乎几乎没有使用任何内存。

问题

我已经开始在我打算最终成为生产代码的形式中使用与上面示例类似的管道,并且copy_to()到目前为止似乎成功地避免了通过 RAM 进行复制。除非我遗漏了什么,否则dbplyr似乎(部分)提供了经常要求的在 R 中处理内存不足数据的能力,就像 SAS 一样——至少在遇到dbplyr无法转换为 SQL 或这是无法接受tbl本机的(例如,我假设有多种建模功能?)。

也许我的案例和 github 发帖者的案例之间的区别在于我只使用一个数据库,而他们试图在两个数据库之间进行传输,但我仍然对 Hadley 的回应感到困惑。dbplyr 简介明确指出,该软件包的主要目的之一是使处理不适合 RAM 的数据变得更容易,所以我对他所说的用于“较小数据集”的意思感到困惑。并且“在自己的数据管道中处理”是否意味着编写自己的 SQL?我试图理解他在谈论什么限制,因为我已经(暂时)dbplyr在我的更多代码中采用。

标签: rdplyrdbidbplyr

解决方案


推荐阅读