2015-09-02 53 views
4

我想從我的文章模型中獲取所有ID。我能做到這一點有兩種方式:ActiveRecords select(:id).collect vs. pluck(:id)方法:爲什麼純粹的AR「採摘」比較慢?

Article.select(:id).collect{|a| a.id} 
    Article Load (2.6ms) SELECT "articles"."id" FROM "articles" 

OR

2.2.1 :006 > Article.pluck(:id) 
    (4.3ms) SELECT "articles"."id" FROM "articles" 

是怎麼回事?爲什麼AR比Ruby版本慢?

即使我標杆紅寶石方法,它似乎更快:

Benchmark.measure{Article.select(:id).collect{|a| a.id}} 
    Article Load (1.9ms) SELECT "articles"."id" FROM "articles" 
=> #<Benchmark::Tms:0x007feb12060658 @label="", @real=0.026455502957105637, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.020000000000000018, @total=0.020000000000000018> 
+0

您是否在測試時禁用數據庫和Rails堆棧中的緩存?您的數據庫中有多少條記錄?文章列表中是否有大的專欄(例如描述博客)? – spickermann

+1

再次檢查您的基準測試:http://rubyinrails.com/2014/06/05/rails-pluck-vs-select-map-collect/ – Nathan

+0

您CA真正做到這三路:「Article.all.collect {|一| a.id}「將是默認的Ruby方式,如果你對它進行基準測試,那麼你會發現它比較慢。你的第一個例子是完全Rubyish方法和爲速度優化的方法之間的中間方法。 –

回答

4

你的基準是不準確的。首先,您可以看到,數據庫端的兩個執行都觸發相同的查詢。因此,數據庫時間應視爲不相關。顯然,兩個查詢的執行時間與控制檯顯示的不同,但這是正常的,因爲如果您運行相同的查詢100次,則執行時間可能每次都不同,因爲它取決於各種變量,例如機器負載,數據庫狀態等

由於數據庫執行時間可以視爲等同,這是無關緊要的基準。

因此,您需要比較的是Ruby執行時間和分配。 Pluck與collect相比應該更快,更輕量,它不會分配ActiveRecord對象,而是隻返回選定的值。

如果你真的想基準的方法,你應該嘲笑數據庫時(這顯然是可變的,但無關緊要對於這個基準測試),只有基準配置和兩個不同的Ruby方法。

長話短說,pluck通常更有效。

+0

只有那個參數的問題是拔取發生在數據庫中,所以在進行比較時將其從等式中移除是沒有意義的。也許一個更好的測試將會得到一個平均值,因爲你忽略了100次運行查詢的觀點。在所有其他方面的點! – Nathan

+0

@Simore你能否提供一個測試prooving'pluck'更有效率嗎?我很好奇,因爲在我自己的實驗中,它要麼陷入錯誤的邊緣,要麼實際上比'find_by!'慢。我用基準ips,禁用查詢緩存,SQL是相同的。非常令人驚訝 – RocketR

1

select被用來獲取具有特定屬性的記錄。它返回一個ActiveRecord::Relation對象。

pluck可以使用相同的方式使用select,但它返回一個選定屬性的數組。

你可以通過this article