Rails 上的大结果 Ruby

Large Results Ruby on Rails

我正在通过播种约 10,000 条记录来测试网站的性能。

我想将它们全部呈现到一个输出页面。

假设我有一个 User 模型(10,000 个用户),我想将它们全部呈现在一个页面上(假设我希望将它们全部预加载到搜索框中,所以我需要同时提供所有记录,我知道这个确切示例有解决方案,但请继续...)。

几个问题:

  1. batch 如何找到工作,有什么方法可以在 controller/model 级别以较小的增量(在后台)找到这些记录,而不仅仅是通过添加自动滚动或分页到视图?

  2. 我不需要用户的所有数据,所以我也可以使用 .pluck。因此,例如,理论上我可能能够做 User.pluck(:date_or_birth),但是如果我有一个 age 方法用于 User,其中 user.age 会 return 基于 .date_of_birth 属性的年龄整数。有没有像pluck一样轻量级的方法可以让我们抓取方法(即.pluck_method(:age))。我在这里遇到的问题是我想要显示的某些内容不是属性,但我可以提取属性并作为 helper?

  3. 进行任何属性操作
  4. 如果我使用 pluck,我的集合现在是 array 而不是 ActiveRecord 哈希,最好转换为 hash 还是按顺序访问数组?

只是想尽可能快地制作几个不同的网站,通常代码很快,但我需要它需要按比例进行操作。

随着数据集的增长,将所有记录呈现到一个页面中将不可避免地不再是一个可行的解决方案。您最终会遇到有限的服务器端 resources/processing 时间以及 Web 客户端 运行 的限制。当然,您需要进行自己的分析和基准测试以确定边界在哪里。到那时,以下内容可以回答您的问题:

  1. (a) Rails 在 ActiveRecord::Relation 上提供 .find_each 方法。它会将大型查询分批处理成较小的块(默认情况下为 1000 条记录),以避免过度使用数据库并将整个数据集一次加载到内存中。您的查询可能类似于:User.find_each(batch_size: 2000) Read more on find_each here。另请查看同一页面上的 find_in_batches

    (b) find_each 只会解决一半的问题,因为 Rails 在将整个页面视图和模板发送回客户端之前在内存中呈现。 ActionController::Streaming 提供增强功能,在呈现页面时将页面的位逐渐发送回客户端。

    Streaming inverts the rendering flow by rendering the layout first and streaming each part of the layout as they are processed. This allows the header of the HTML (which is usually in the layout) to be streamed back to client very quickly, allowing JavaScripts and stylesheets to be loaded earlier than usual.

    This approach was introduced in Rails 3.1 and is still improving. Several Rack middlewares may not work and you need to be careful when streaming. Those points are going to be addressed soon.

    In order to use streaming, you will need to use a Ruby version that supports fibers (fibers are supported since version 1.9.2 of the main Ruby implementation).

    (c) 我强烈建议您也看看一些不同的缓存技术,以避免重新呈现视图,甚至完全避免访问数据库。 rails caching guides 很好地概述了可能适用于您的项目的不同技术。

  2. 您可以使用select方法代替pluck来限制从数据库中检索的数据到您感兴趣的一个或多个数据库列。Select 将 return 一组 ActiveRecord 就像一个典型的查询一样,除了只有指定的属性将被填充到内存中。使用 select(:date_of_birth),您可以使用 user.age 方法。

  3. select 在这里对您来说可能也是一个更好的解决方案。要记住的一件事是,与使用 pluck 获得的简单数组相比,为每条记录实例化 AR 对象将增加所需的内存并使用额外的 CPU 周期。