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

时间:2011-05-14 22:19:51

标签: ruby datamapper ruby-datamapper

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

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

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

有没有办法告诉Datamapper以块的形式加载结果?知道这样做是否足够聪明?

3 个答案:

答案 0 :(得分:4)

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

while authors = Author.slice(offset, CHUNK) do
  authors.each do |a|
    # do something with a
  end
  offset += CHUNK
end

答案 1 :(得分: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​​查询数和内存使用量之间的良好折衷。

答案 2 :(得分:2)

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

require 'dm-chunked_query'

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

这将允许您一次以20个记录的块为单位迭代模型中的所有记录。

编辑:上面的示例在#each之后有一个额外的#each_chunk,这是不必要的。 gem作者更新了README示例,我将上面的代码更改为匹配。