In Rails, what's the difference between find_each and where?

In Rails, both find_each and where are used for retrieving data from Database supported by ActiveRecord.

You can pass your query condition to where, like:

c = Category.where(:name => 'Ruby', :position => 1)

And you can pass batch size to find_each, like:

Hedgehog.find_each(batch_size: 50).map{ |p| p.to_json }

But what's the difference between the following 2 code?

# code 1
Person.where("age > 21").find_each(batch_size: 50) do |person|
# processing
end


# code 2
Person.where("age > 21").each do |person|
# processing
end

Does code 1 batch retrieve 50 tuples each time, and code 2 retrieve all tuples in one time? More details explaination is welcomed.

My opinion is:

  1. both where and find_each can be used for batch retrieving, but user can define batch size when using find_each.
  2. find_each does not support passing query condition.

Please correct me if my understanding is wrong.

50295 次浏览

An active record relation does not automatically load all records into memory.

When you call #each, all records will be loaded into memory. When you call #find_each, records will be loaded into memory in batches of the given batch size.

So when your query returns a number of records that would be too much memory for the server's available resources, then using #find_each would be a great choice.

It's basically like using ruby's lazy enumeration #to_enum#lazy with #each_slice and then #each (very convenient).

Answering Jin Lim's question. The statement users = User.where(:birth_day < Date.today) does not load all the data in users variable as the statement has not executed yet and is due to lazy loading supported by Rails. When you call each on users, then all of the data would be loaded into memory.