2016-01-01 48 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 

希望它能幫助。