我在控制器中定义了三个实例变量。最后两个使用第一个的值。每次第一个用于计算另一个变量时,是否必须重新计算?
换句话说,哪种方法更快?
方法1
def show
@things = Thing.all.where(boolean: true)
@things_decreasing = @things.reverse
@things_random = @things.shuffle
end
方法2
def show
@things = Thing.all.where(boolean: true)
@things_decreasing = Thing.all.where(boolean: true).reverse
@things_random = Thing.all.where(boolean: true).shuffle
end
答案 0 :(得分:4)
两种方法的性能几乎相同,因为Thing.all.where(boolean: true)
会返回ActiveRecord::Relation
的实例。 ActiveRecord::Relation
不会立即执行数据库查询,而是在需要数据的第一个方法调用(此示例中为reverse
)上执行。
方法2创建新的(但相似的)关系对象,而方法1重用相同的关系对象。性能几乎相同,因为与运行多个数据库调用相比,创建该关系的速度非常快,并且两个示例都有相同数量的数据库调用。
但是有一种方法可以加快速度:示例中的两个方法只执行一次数据库调用,因为Rails在数据库连接器中缓存数据库调用。但是Rails会重新生成缓存数据库对每个查询的响应结果,并且每次都会返回一个包含新实例的新数组。
将所有对象加载到数组中并重用该数组可能会更快(取决于数据库响应的大小):
def show
# triggers the database call and returns an array (not a Relation)
@things = Thing.where(boolean: true).to_a
# re-use the result from the @things array, and not a Relation object
@things_decreasing = @things.reverse
@things_random = @things.shuffle
end
答案 1 :(得分:0)
@things = Thing.where(boolean: true).to_a
Benchmark.measure{@things_decreasing = @things.reverse}
使用Benchmark可以检查性能时间。为了提高性能,最好使用返回的数组。