从sqlite导入非常大的数据集到h2o中。

问题描述 投票:1回答:1

我有一个大约500G的数据库。它由16张表组成,每张表包含2或3列(第一列可以舍弃)和1,375,328,760行。我需要在h2o中把所有的表连接成一个数据框,因为它们需要在XGB模型中运行一个预测。我试着使用as.h2o将单个sql表转换到h2o环境中,并且h2o.cbind一次连接2或3个表,直到它们成为一个数据集。但是,我在转换了4张表之后,得到了 "GC overhead limit exceeded: java.lang.OutOfMemoryError",有什么办法解决这个问题吗?我的机器规格是124G内存,操作系统(Rhel 7.8),Root(1tb),Home(600G)和2TB外置硬盘,模型在这台本地机器上运行,max_mem_size设置为100G。代码的细节如下。

library(data.table)
library(h2o)          
h2o.init(
  nthreads=14,          
  max_mem_size = "100G")    
h2o.removeAll() 

setwd("/home/stan/Documents/LUR/era_aq")

l1.hex <- as.h2o(d2)
l2.hex <- as.h2o(lai)
test_l1.hex <-h2o.cbind(l1.hex,l2.hex[,-1])
h2o.rm (l1.hex,l2.hex)
l3.hex <- as.h2o(lu100)
l4.hex <- as.h2o(lu1000)
test_l2.hex <-h2o.cbind(l3.hex,l4.hex[,-1])
h2o.rm(l3.hex,l4.hex)
l5.hex <- as.h2o(lu1250)
l6.hex <- as.h2o(lu250)
test_l3.hex <-h2o.cbind(l5.hex,l6.hex[,-1])
h2o.rm(l5.hex,l6.hex)
l7.hex <- as.h2o(pbl)
l8.hex <- as.h2o(msl)
test_l4.hex <-h2o.cbind(l7.hex,l8.hex[,-1])
h2o.rm(ll7.hex,l8.hex)

test.hex <-h2o.cbind(test_l1.hex,test_l2.hex[,-1],test_l3.hex[,-1],test_l4.hex[,-1])
test <- test.hex[,-1]
test[1:3,]```
r sqlite h2o
1个回答
2
投票

首先,正如Tom在评论中所说,你需要一条更大的船。H2O在内存中保存着所有的数据,一般来说,你需要3到4倍的数据大小才能对它做任何有用的事情。一个500GB的数据集意味着你需要集群的总内存是1.5-2TB。

(H2O存储的数据是经过压缩的,我想sqlite不会,在这种情况下,你可能只需要1TB就可以了)。

第二,你的集群需要的内存是1.5-2TB。as.h2o() 是一种加载大数据集的低效方式。会发生的情况是你的数据集被加载到R的内存空间中,然后保存到csv文件中,然后这个csv文件通过TCPIP流式传输到H2O进程中。

所以,更好的方法是直接从sqlite导出到csv文件。然后用 h2o.importFile() 来将该csv文件加载到H2O中。

h2o.cbind() 也会涉及到大量的复制工作。如果你能找到一个工具或脚本,在导入前对csv文件进行列式绑定,可能会更有效率。快速搜索发现 csvkit但我不确定它是否需要将文件加载到内存中,还是可以完全在磁盘上使用文件进行工作。


1
投票

由于内存是很宝贵的,而且所有的R都是在RAM中运行的,所以要避免存储大的辅助程序。data.tableh20 对象的全局环境中。考虑设置一个函数来为编译建立一个列表,当函数超出范围时,临时对象会被删除。理想的情况是,你在编译时建立你的 h2o 直接从文件源导出对象。

# BUILD LIST OF H20 OBJECTS WITHOUT HELPER COPIES
h2o_list <- lapply(list_of_files, function(f) as.h2o(data.table::fread(f))[-1])
# h2o_list <- lapply(list_of_files, function(f) h2o.importFile(f)[-1])

# CBIND ALL H20 OBJECTS
test.h2o <- do.call(h2o.cbind, h2o_list)

或者把这两行代码结合起来,用命名函数来代替匿名函数。然后,在处理后只剩下最后的对象。

build_h2o <- function(f) as.h2o(data.table::fread(f))[-1])
# build_h2o <- function(f) h2o.importFile(f)[-1]

test.h2o <- do.call(h2o.cbind, lapply(list_of_files, build_h2o))

扩展函数 if 对于一些需要保留第一列或不需要保留第一列的数据集。

build_h2o <- function(f) {
   if (grepl("lai|lu1000|lu250|msl", f)) { tmp <- fread(f)[-1] }
   else { tmp <- fread(f) }

   return(as.h2o(tmp))
}

最后,如果可能的话,利用 data.table 方法,如 cbindlist:

final_dt <- cbindlist(lapply(list_of_files, function(f) fread(f)[-1]))

test.h2o <- as.h2o(final_dt)

rm(final_dt)
gc()
© www.soinside.com 2019 - 2024. All rights reserved.