在Rails 3.2中,如何“ pluck_in_batches”一个非常大的表

jpw*_*ynn 5 activerecord ruby-on-rails pluck

我有一个庞大的表Foo,我需要从中提取特定字段Foo.who中的所有值。

该数组具有数百万行,但列中只有几千个不同的值who。

如果桌子较小,我当然会用 Foo.pluck(:who)

如果我使用的Foo.find_in_batches do |a_batch|每个集合都是Foo记录的数组,而不是Foo记录的activerecord集合,那么我不能使用.pluck()AFAIK和AFAIK提取who列的唯一方法是通过.map(&:who)对数组进行迭代的方式。

有没有一种方法可以who批量从Foo中拔出色谱柱,而无需在每个批次的每个元素上进行迭代以提取who色谱柱?

Dmi*_*lov 15

在 Rails 5 中你可以使用:

Foo.in_batches do |relation|
  values = relation.pluck(:id, :name, description)
  ...
end
Run Code Online (Sandbox Code Playgroud)

更新:为了防止内存泄漏,请使用:

Foo.uncached do
  Foo.in_batches do |relation|
    values = relation.pluck(:id, :name, description)
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我懂了。看起来 in_batches 已经这样做了 https://github.com/rails/rails/blob/85c6823b77b60f2a3a6a25d7a1013032e8c580ef/activerecord/lib/active_record/relation/batches.rb#L226 (至少对于 Rails >= 5.2)。但不确定它是否仍然适用于“relation.pluck”。 (7认同)
  • 您能否详细说明内存泄漏问题以及“Foo.uncached”如何/为什么有帮助?我也很感兴趣这是否也适用于 Rails 6.0/6.1。 (4认同)

Gui*_*iGS 5

这是一种获取方法本身检索到的 id 的方法in_batches,无需您自己运行另一个查询。

in_batches已经pluck(:id)在后台运行(当loadparam 是false默认值时)并产生关系对象。该关系对象是使用 创建的where(id: ids_from_pluck)。

是否可以通过方法直接从关系对象获取 id 列表where_values_hash,而不需要在数据库中运行另一个查询。例如:

Foo.in_batches do |relation|
  ids = relation.where_values_hash['id']
end
Run Code Online (Sandbox Code Playgroud)

这应该适用于 Rails 5.x 和 6.x,但它依赖于实现细节,in_batches因此不能保证将来也能工作。


小智 0

尝试这个:

Foo.select(:id, :who).find_in_batches do |a_batch|
  ...
end
Run Code Online (Sandbox Code Playgroud)

  • 这仍然会创建 ActiveRecord 对象,我认为出于内存和速度原因,OP 正在尝试避免这种情况。 (5认同)