【发布时间】:2012-10-09 07:36:51
【问题描述】:
在某些情况下,当我获得 ActiveRecord 关系时,我会在 ActiveRecord::Relation 上遇到 .each 的奇怪行为
似乎是 ActiveRecord::Relation 将 :each 委托给 :to => :to_a (source)
@tasks = Task.find_task(list, {:week_id => 1})
基本上,有一个冗长的类方法接受一个对象(list,以及带有:week_id 的哈希)
在这个 find_task 方法中发生了一堆过滤和查询,但它最终返回了与 @tasks 的关系
然后,在模板中,我有:
<% @tasks.each do |task| %>
.
.
.
<% end %>
无论出于何种原因,无论@tasks 的大小如何,都需要大约 3 分钟。我可以通过调用@tasks.to_a 来复制同样的行为即使@tasks,ActiveRecord::Relation 的一个实例只有两条记录,在它们上调用to_a 也需要> 3 分钟。
它不会发生在所有:week_ids 上,只会发生在特定的 week_id 上,例如::week_id => 1
SQL 执行良好,我得到了一个关系,这似乎是特定 ActiveRecord::Relation 上的可枚举问题。
更新
在算法内部(我认为这意味着类方法)我做了很多急切加载。所以 Postgres 做了很多 LEFT OUTER JOINs,我已经索引了所有需要发生这种情况的表。
解释分析显示所有扫描都是index scans,事实证明查询执行得很好,需要大量的急切加载......我得到一个合理数量的急切加载的“ActiveRecord::Relation”时间。
更新 2
虽然这个过程需要 3 分钟,但我看到一个 postgres 进程运行了几秒钟,然后我在 top 中看到了 3 分钟作为我的输出:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8685 dylan 20 0 3407m 2.6g 904 R 99.7 69.1 1:14.49 /usr/local/bin/ruby script/rails s
当它最终完成时,服务器会显示这个;
- 渴望加载:
200 ms,139 ms然后 - 一个包含大量
LEFT OUTER JOINS in 33,000 ms的大型 SQL 查询,(很长,但不是大多数)然后 -
257,000 ms在模板中。
当我在模板中复制行为时,我发现在 @tasks 关系上调用 to_a 大约需要 3-4 分钟。
所以,当我的服务器告诉我所有的时间都花在了模板上,并且我可以看到在关系上调用一个可枚举对象需要很长时间时,是在执行查询的时候吗?即使在top 中我只能看到ruby 进程正在运行?
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-3.2 enumerable