在Charge
通过item_id
属性HABTM Item
,我试图找出哪些查询是快的建立:父母使用子对象进行Ruby搜索或使用子标识在父对象上进行搜索?
a = Charge.where(item_id: 1).where(type:"test")
b = Item.find(id:1).charges.where(type:"test")
我觉得a
可能更快,因为你只需要看看一张桌子,但对实际答案感兴趣。
在Charge
通过item_id
属性HABTM Item
,我试图找出哪些查询是快的建立:父母使用子对象进行Ruby搜索或使用子标识在父对象上进行搜索?
a = Charge.where(item_id: 1).where(type:"test")
b = Item.find(id:1).charges.where(type:"test")
我觉得a
可能更快,因为你只需要看看一张桌子,但对实际答案感兴趣。
您的直觉是正确的:
a
速度快得多,因为它只在一个表上运行一条SQL语句。
b
做不同的东西共:
Item
类型(Item.find(id:1)
)charges
查询的Charges
列表的第二个步骤,它等效(查询a
很明显(不使用benchmark
:-)),a
是b
的真子集,因此速度更快。
另一方面:b
更面向对象,更一般。因此,如果由于任何原因,物品和费用之间的关联不是RoR标准(即,您必须使用不同的对准关键字),b
仍然可以使用,而a
必须进行调整。
其中泛化花费某些速度的例子之一。
运行benchmark一度使得完全没有意义的,基准是因为所产生的执行时间超过1s(摆脱的副作用,比如意外HDD等待时间,或什么的。)
将至少运行多次不幸的是,仅仅在一个循环中运行基准测试 - 由于rails缓存原因也没有任何意义。因此,正确的答案可能是:“应该禁用任何rails缓存并在循环中运行数千次基准。”在默认配置中禁用任何rails缓存的最简单方法是在执行前设置环境变量RAILS_ENV=development
。
require 'benchmark'
n = 50000
Benchmark.bm do |x|
x.report { n.times { Charge.where(item_id: 1).where(type:"test") } }
x.report { n.times { Item.find(id:1).charges.where(type:"test") } }
end
但我会用ActiveRecord#to_sql
方法去。您可能会打印出两个查询,并根据数据库执行rails构建,并检查打印的纯SQL。在你的情况下,他们将是几乎相同的(我不知道而现在我无法测试它由于缺乏环境的,但我希望你明白了吧。)
puts Charge.where(item_id: 1).where(type:"test").to_sql
puts Item.find(id:1).charges.where(type:"test").to_sql
希望它能帮助。
你可能会发现哪一个更快你自己在轨道控制台... – MilesStanfield
我该怎么做? – james