What is the difference between count, length, and size?
count、length和size的差異?
在ActiveRecord中有許多方法可以去找到關連性的總數,以下就來解析這些方法的差異
s2 = Song.find(2)
s2.comments.count
SELECT COUNT(*) FROM "comments" WHERE "comments"."song_id" = $1 [["song_id", 2]]
# => 76
s2.comments.count
SELECT COUNT(*) FROM "comments" WHERE "comments"."song_id" = $1 [["song_id", 2]]
# => 76
上面這個例子想對二號歌曲找到他所有的留言總數,count
的特性就是每次使用都一定會觸發SQL COUNT的查詢,所以效能上不是太好,但因為每次執行都是老老實實的去資料庫查詢,所以是最為精準的。
同樣的例子來對比length
方法
s2 = Song.find(2)
s2.comments.length
SELECT "comments".* FROM "comments" WHERE "comments"."song_id" = $1 [["song_id", 2]]
#=> 76
s2.comments.length
#=> 76
length方法會將所有關聯性的內容全部都撈出來存在記憶體當中,然後回傳有多少元素被載入,在只要計算總數目的來看效能上是最差的。
但可以看到我們第二次執行length
方法的時候,並不會再去撈一次資料庫,畢竟前面都已經將所有的內容都撈過一次了,所以第二次只會再去數一次。所以在前面已經load過這些資料,可以使用length
來避免資料庫的重複查詢。
而size
這個方法就是count
與length
的綜合體,為什麼會這麼說呢?
來看原始碼就知道了
# File activerecord/lib/active_record/relation.rb, line 210
# Returns size of the records.
def size
loaded? ? @records.length : count(:all)
end
如果關係已經被載入(load),我們就對已經載入的Array執行length
方法,而如果資料ActiveRecord::Relation沒有被載入,我們就觸發count的查詢。
使用時機可以總結為以下幾點
length
可以避免再一次的資料庫查詢count
方法查詢資料庫size
方法會是個好選擇count
方法每次執行時都會對資料庫進行COUNT查詢,只有當我們當下真的要去算總數時才會使用count
方法length
方法在資料還沒載入時,會將所有關聯資料內容拉出來存在記憶體當中,回傳被載入的個數,以計算總數的效能上是最不好的。不過當資料已經在前面被載入時,使用length
方法能讓我們減少資料庫的查詢次數。size
方法是count
與length
的總和,當資料已經被載入過,使用size
就等同於使用length
方法,如果沒有的話,會幫我們使用count
查詢。1.ActiveRecord: size vs count vs length
3.3 ActiveRecord Mistakes That Slow Down Rails Apps: Count, Where and Present