Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nightire/5124427 to your computer and use it in GitHub Desktop.
Save nightire/5124427 to your computer and use it in GitHub Desktop.
Rails 4 - Active Record Query Interface

Rails 4 - Active Record Query Interface

批量查询记录

我们时常会碰到需要一次性处理大量记录的要求,比如说为所有的用户发送电子邮件:

User.all.each do |user|
  NewsLetter.weekly_deliver(user)
end

这样的做法虽然能完成工作,但是却很没效率,特别是当数据库里的记录数量非常大的时候,User.all 会把所有的记录一次性获取,然后逐条实例化,并把最终的结果数组保存在内存当中,这种消耗是非常巨大的。

Rails 提供了两个用于批量查询记录的方法,find_eachfind_in_batches

find_each

find_each 方法查询一批记录并逐条提取至 block 中执行,一批次的数量默认是 1000 条,这个缺省值是和 find_in_batches 相同的。

User.find_each do |user|
  NewsLetter.weekly_deliver(user)
end

当然,我们可以手动指定一批次的数量:

User.find_each(batch_size: 5000) do |user|
  NewsLetter.weekly_deliver(user)
end

另外,默认的查询是以主键按升序来完成的,这就要求主键必须得是数字;我们还可以指定查询的起始位置:

User.find_each(start: 2000, batch_size: 2000) do |user|
  NwesLetter.weekly_deliver(user)
end

假设你想要同时使用多个代工(workers)来帮助你处理批量工作,就可以用这两个选项来为每一个代工指定目标区间了。

find_in_batches

find_each 相比,find_in_batches 方法在获得一批记录之后,并不是逐条提取而是把这一批记录作为一个数组全部提取至 block 中执行。

Invoice.find_in_batches(include: :invoice_lines) do |invoices|
  export.add_invoices(invoices)
end

include 选项允许你指明需要和模型一起加载的关联关系*,其他的选项和 find_each 方法相同。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment