It’s important to know the differences between these three methods to ensure you’re triggering the fewest or most optimized SQL queries possible.
The count
method always triggers a SELECT count(*) FROM table
query.
The length
method ensures that the relationship has been loaded to count in memory.
The size
method adapts to the loading of the relationship. Either it triggers a query if it hasn't been loaded, or it counts in memory if it has already been loaded.
Here's a summary table:
Records Loaded | Record Not Loaded | |
---|---|---|
count |
SELECT count(*) FROM table |
SELECT count(*) FROM table |
size |
Count in memory | SELECT count(*) FROM table |
length |
Count in memory | SELECT * FROM table |
When counting and enumerating, it’s important to call size after the relationship has been loaded. In all cases, the aim is to trigger a single request.
# Bad 2 queries instead of 1
users = User.all
users.size # SELECT count(*) FROM "users"
users.each {} # SELECT "users".* FROM "users" # Good
users = User.all
users.length # SELECT "users".* FROM "users"
users.each { } # No queries # Good
users = User.all
users.each { } # SELECT "users".* FROM "users"
users.size # No queries # Good
users = User.all.load # SELECT "users".* FROM "users"
users.size # No queries
users.each { } # No queries # Bad 2 queries instead of 1
users = User.all
users.each { } # SELECT "users".* FROM "users"
users.count # SELECT COUNT(*) FROM "users"