2016-01-01 44 views
1

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可能更快,因为你只需要看看一张桌子,但对实际答案感兴趣。

+1

你可能会发现哪一个更快你自己在轨道控制台... – MilesStanfield

+0

我该怎么做? – james

回答

1

您的直觉是正确的:
a速度快得多,因为它只在一个表上运行一条SQL语句。

b做不同的东西共:

  • 它搜索和实例化Item类型(Item.find(id:1)
  • 的一个目的在它使用的关联charges查询的Charges列表的第二个步骤,它等效(查询a

很明显(不使用benchmark :-)),ab的真子集,因此速度更快。

另一方面:b更面向对象,更一般。因此,如果由于任何原因,物品和费用之间的关联不是RoR标准(即,您必须使用不同的对准关键字),b仍然可以使用,而a必须进行调整。

其中泛化花费某些速度的例子之一。

1

运行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 

希望它能帮助。