Ga Tech

1.01 everyday

Rails 的 count, length 以及 size

列出 count, length 以及 size 的特性:

count

  • 使用 SQL query (SELECT COUNT(*) FROM…)
  • 不會儲存計算物件,每次執行 count 都會重新跑一次 SQL query
  • 速度比 length
1
2
3
4
5
6
7
8
2.1.2 :001 > collection = User.all ; nil
=> nil
2.1.2 :002 > collection.count
(0.4ms) SELECT COUNT(*) FROM `users`
=> 284
2.1.2 :003 > collection.count
(0.4ms) SELECT COUNT(*) FROM `users`
=> 284

length

  • 回傳一個集合的長度
  • 計算物件會儲存在記憶體中
  • 如果是 eager loaded 的物件,執行速度會非常快
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2.1.2 :004 > collection = User.all ; nil
=> nil
2.1.2 :005 > collection.length
User Load (1.5ms) SELECT `users`.* FROM `users`
=> 284
2.1.2 :006 > collection = User.all ; nil
=> nil
2.1.2 :007 > collection.to_a ; nil
User Load (1.6ms) SELECT `users`.* FROM `users`
=> nil
2.1.2 :008 > collection.length
=> 284
2.1.2 :009 > collection.length
=> 284

size

  • 綜合上述兩者的特性
  • 如果是已經在記憶體中的集合,就直接計算長度 (不會有額外的 query)
  • 如果是 lazy loaded 的集合,就會直行 SQL query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2.1.2 :010 > collection = User.all ; nil
=> nil
2.1.2 :011 > collection.count
(2.9ms) SELECT COUNT(*) FROM `users`
=> 284
2.1.2 :012 > collection.count
(0.7ms) SELECT COUNT(*) FROM `users`
=> 284
2.1.2 :013 > collection.size
(0.7ms) SELECT COUNT(*) FROM `users`
=> 284
2.1.2 :014 > collection.to_a ; nil
User Load (2.9ms) SELECT `users`.* FROM `users`
=> nil
2.1.2 :015 > collection.size
=> 284

結論

記得在合適的情況使用這些 method,否則可能會因為不必要的 collection loading 造成浪費。
如果還是不知道該怎麼分辨使用時機的話,就用 size 吧!

source: http://dev.mensfeld.pl/2014/09/activerecord-count-vs-length-vs-size-and-what-will-happen-if-you-use-it-the-way-you-shouldnt/

Comments