When working with Active Record in Ruby on Rails, we often need to count the number of records. There are three main methods for this: .count
, .length
, and .size
. Each of these methods behaves differently, and understanding these differences can help you write more efficient code.
Rails version
7.1.3.4
The .count Method
The .count
method always performs a COUNT query to the database. This is true regardless of whether the records are loaded into memory or not. Here’s an example:
posts = Post.all
posts.count
# Post Count (1.8ms) SELECT COUNT(*) FROM "posts"
# => 1000
posts = Post.all; posts.count; posts.count
# Post Count (3.9ms) SELECT COUNT(*) FROM "posts"
# Post Count (0.7ms) SELECT COUNT(*) FROM "posts"
# => 1000
Even if the records are already loaded into memory, .count will still perform a COUNT query:
posts = Post.all.load
# Post Load (2.6ms) SELECT "posts".* FROM "posts"
# => [#<Post id: 1...
posts.count
# Post Count (1.2ms) SELECT COUNT(*) FROM "posts"
# => 1000
The .length Method
On the other hand, the .length
method loads the records into memory if needed. So, if the records are already loaded, .length
will return the number of records without performing a new query:
posts = Post.all
# Post Load (1.0ms) SELECT "posts".* FROM "posts" /* loading for pp */ LIMIT $1 [["LIMIT", 11]]
posts.length
# Post Load (3.3ms) SELECT "posts".* FROM "posts"
# => 1000
posts = Post.all; posts.length; posts.length
# Post Load (4.2ms) SELECT "posts".* FROM "posts"
# => 1000
The .size Method
Lastly, the .size
method performs a COUNT query if the records are not loaded. However, if the records are already loaded, .size
will return the number of records without performing a new query:
posts = Post.all
# Post Load (0.5ms) SELECT "posts".* FROM "posts" /* loading for pp */ LIMIT $1 [["LIMIT", 11]]
posts.size
# Post Count (0.9ms) SELECT COUNT(*) FROM "posts"
# => 1000
posts = Post.all; posts.size; posts.size
# Post Count (1.2ms) SELECT COUNT(*) FROM "posts"
# Post Count (1.0ms) SELECT COUNT(*) FROM "posts"
# => 1000
posts = Post.all.load; posts.size; posts.size
# Post Load (6.3ms) SELECT "posts".* FROM "posts"
# => 1000
Review count vs length vs size with a Diagram
Each of these methods is similar, but I think you'll find that they work differently than you might imagine. If we can understand them, we can choose the appropriate method and optimize the performance of our application.
That is about it. Happy coding!
Top comments (0)