2

使用 Datamapper 遍历整个表的最有效方法是什么?

如果我这样做,Datamapper 是否会在执行迭代之前尝试将整个结果集拉入内存?假设,为了论证,我有数百万条记录,这是不可行的:

Author.all.each do |a|
  puts a.title
end

有没有办法告诉 Datamapper 以块的形式加载结果?知道自动执行此操作是否足够聪明?

4

3 回答 3

4

谢谢,尼古拉斯,我实际上想出了一个类似的解决方案。我已经接受了你的回答,因为它使用了 Datamapper 的dm-pagination系统,但我想知道这是否会同样好(或更糟):

while authors = Author.slice(offset, CHUNK) do
  authors.each do |a|
    # do something with a
  end
  offset += CHUNK
end
于 2011-05-15T01:58:51.850 回答
2

对于上面的示例,Datamapper 将只运行一个 sql 查询,因此它必须将整个结果集保存在内存中。

如果您的收藏很大,我认为您应该使用某种分页。使用dm-pagination您可以执行以下操作:

PAGE_SIZE = 20
pager = Author.page(:per_page => PAGE_SIZE).pager # This will run a count query
(1..pager.total_pages).each do |page_number|
  Author.page(:per_page => PAGE_SIZE, :page => page_number).each do |a|
    puts a.title
  end
end

您可以使用不同的 PAGE_SIZE 值来在 sql 查询数量和内存使用量之间找到一个很好的折衷。

于 2011-05-15T00:20:14.513 回答
2

您想要的是 dm-chunked_query 插件:(来自文档的示例)

require 'dm-chunked_query'

MyModel.each_chunk(20) do |chunk|
  chunk.each do |resource|
    # ...
  end
end

这将允许您迭代模型中的所有记录,一次包含 20 条记录。

编辑:上面的例子有一个额外的#eachafter #each_chunk,这是不必要的。gem作者更新了README的例子,我把上面的代码改成匹配了。

于 2011-05-15T02:50:13.243 回答