Dùng find_each. User.all.each nạp toàn bộ 5 triệu dòng vào RAM trước khi lặp — process rất dễ bị OOM kill.
find_each chia thành từng lô (mặc định 1000 record), nạp lô nào xử lý lô đó rồi giải phóng:
ruby
User.where(active: true).find_each(batch_size: 500) do |user|
ReportJob.perform_later(user.id)
end
# find_in_batches trả về cả batch dưới dạng mảng
User.find_in_batches(batch_size: 1000) { |batch| Mailer.bulk(batch).deliver_later }
# in_batches trả về Relation, nên chạy được UPDATE theo tập cho từng batch
User.in_batches(of: 1000) { |rel| rel.update_all(synced_at: Time.current) }Lưu ý: find_each ép sắp xếp theo primary key và bỏ qua order bạn đặt (Rails sẽ cảnh báo).
Nếu bắt buộc phải theo thứ tự khác thì phải tự phân trang bằng khoá (keyset pagination) chứ không dùng find_each.