一般说明
您不必加载所有数据以进行采样,只需加载行的 id 并从 id 中采样。然后仅加载采样行的数据。更详细:
例如如果您的数据库中有一个名为ID 的列,则仅加载此列。这应该很快,特别是如果ID 是一个整数。即使你有(比如说)20 亿条记录,你也只需要 8GB 内存来存储 20 亿个整数,所以这应该是可能的。
然后从这些 id 中采样。
然后仅加载具有采样 id 的记录。
想想吧。如果你想从网上书店Siren随机购买三本书,你会怎么做? Siren 有几百万本书,你不能全部订购,然后在它们之间随机选择,然后把剩下的寄回去,对吧?所以你要做的是,你向 Siren 索要书籍 ID 的列表(ISBN 会做),它的大小适合一台普通的计算机。您从列表中随机选择三个,然后从 Siren 订购这三个。
Rdata 文件
这显然不适用于 .Rdata 文件,但 .Rdata 文件无论如何都没有希望,因为您无法加载 .Rdata 文件的一部分。所以你需要一些被索引的格式。
sqlite
但是你可以使用 sqlite 和 RSQLite 包。 RSQLite 支持与数据框绑定,因此要加载采样数据,您只需将采样的 id 放入名为 samp_ids 的数据框(单列名为 id),然后说类似
...
my_samp <- dbGetQuery(con, "SELECT * FROM mytable WHERE id = :id",
bind.data = samp_ids)
...
这将读取带有采样 id 的记录。
MySQL
上次我检查RMySQL 不支持绑定,所以这可能不是要走的路。如果您坚持使用 MySQL,那么我会尝试的第一件事是创建一个临时表,其中仅包含采样的行 ID,然后将该表与您的数据表 JOIN。这是由RMySQL 支持的,它的工作原理是这样的:
dbSendQuery(con, "CREATE TEMPORARY TABLE tmp (id INTEGER);")
## Stupid, but this seems to be necessary to really create the
## temporary table, it is an RMySQL bug that I reported long time
## ago: https://github.com/jeffreyhorner/RMySQL/issues/10
try(dbSendQuery(con, "CREATE TEMPORARY TABLE tmp (id INTEGER);"))
dbWriteTable(con, "tmp", samp_ids, row.names=FALSE, append=TRUE)
然后你可以写你的SELECT来JOIN临时表tmp和你的原始数据表。