4

我正在一个现有的 Rails 2 站点上工作,该站点具有最近更新到 Ruby 1.9.2 和 mysql2 gem 的大型代码库。我注意到这个设置允许非阻塞的数据库查询;你可以做client.query(sql, :async => true),然后再调用client.async_result,它会阻塞直到查询完成。

在我看来,我们可以通过让所有ActiveRecord返回集合的查询拒绝阻塞,直到在集合上调用方法来提高性能。例如

@widgets = Widget.find(:all, :conditions=> conditions) #sends the query
do_some_stuff_that_doesn't_require_widgets
@widgets.each do #if the query hasn't completed yet, wait until it does, then populate @widgets with the result. Iterate through @widgets
...

这可以通过猴子补丁Base::find及其相关方法来创建一个新的数据库客户端,异步发送查询,然后立即返回一个 Delegator 或其他代理对象,当任何方法被调用时,调用client.async_result,实例化结果使用ActiveRecord, 并将方法委托给它。 ActiveRecord关联代理对象已经以类似的方式实现 ORM。

但是,我找不到任何这样做的人,而且在任何版本的 Rails 中似乎都不是一个选项。我已经尝试自己实现它并且它在控制台中工作(只要我附加; 1到调用所有内容的行,这样to_s就不会在结果中调用它)。但它似乎与其他各种魔法发生碰撞并产生各种问题。

那么,出于某种我没有想到的原因,这是一个坏主意吗?如果没有,为什么它不是ActiveRecord已经工作的方式?有没有一种干净的方法来实现它?

4

1 回答 1

1

我怀疑 .async_result 方法不适用于所有数据库驱动程序;如果没有,它就不能合并到通用的 ActiveRecord 调用中。

在循环大型记录集时提高性能的一种更便携的方法是使用 find_each 或 find_in_batches。我认为它们可以在 rails 2.3 和 rails 3.x 中工作。http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches

于 2012-10-16T12:42:09.970 回答