在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