count
キャッシュしない。
毎回sqlのcountを使ってカウントする。
最新の件数を取得できる。
area = Area.first # 毎回sqlが発行される area.sub_areas.count # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 1 area.sub_areas.count # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 1 # 毎回sqlが発行されるので最新の件数を取得できる SubArea.create!(area_id: 1, ja_name: 'hoge') area.sub_areas.count # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2 area.sub_areas.count # (1.9ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2
length
キャッシュする。
2回目以降はクエリが発行されない。
最新の件数は取得されない。
area = Area.first area.sub_areas.length # SubArea Load (2.8ms) SELECT `sub_areas`.* FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 1 # キャッシュするので2回目以降はクエリが発行されない area.sub_areas.length # => 1 SubArea.create!(area_id: 1, ja_name: 'hoge') # countの場合は最新の件数を取得するが area.sub_areas.count # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2 # # lengthの場合は最新の件数を取得しない area.sub_areas.length # => 1
size
メモリにデータがあればそれを参照し、なければクエリを発行し続けて最新のデータを取得する。
area = Area.first # クエリを発行して最新のデータを取得する area.sub_areas.size # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 1 area.sub_areas.size # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 1 SubArea.create!(area_id: 1, ja_name: 'hoge') area.sub_areas.count # (1.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2 area.sub_areas.size # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2 area.sub_areas.size # (0.4ms) SELECT COUNT(*) FROM `sub_areas` WHERE `sub_areas`.`area_id` = 1 # => 2 areas = Area.all areas.count # (3.7ms) SELECT COUNT(*) FROM `areas` # => 17 areas.length # => 17 # メモリにデータがある場合はそれを参照する areas.size # => 17
使い分けの案
最新のデータを取得したい時はcount。
最新のデータを取得する必要がない時、eachなどの繰り返し処理で使う時はlength。
sizeはキャッシュの状況によって発行されるクエリが変わるので個人的に使いずらい。