Counter Cache Associations

#78 Counter Cache Associations
5/1/2017

Summary

When displaying a count of records, this will generate extra SQL Queries. Learn how to reduce the number of SQL queries called with counter caching the number of associated records.
2
rails model cache 3:54 min

Summary

companies/index.html.erb# Bad
<%= company.users.length %>

# Good
<%= company.users_count %>
<%= company.users.size %>
user.rbclass User < ApplicationRecord
  belongs_to :company, counter_cache: true 
  # DEFAULT Column: users_count
  # belongs_to :company, counter_cache: :users_size 
end

Terminalrails g migration add_counter_cache_to_companies users_count:integer
db/migrate/20170501010016_add_counter_cache_to_companies.rbclass AddCounterCacheToCompanies < ActiveRecord::Migration[5.0]
  def change
    add_column :companies, :users_count, :integer, default: 0
    Company.find_each { |company| Company.reset_counters(company.id, :users) }
  end
end



11652222?v=3&s=64
scytherswings said 3 months ago:

I feel like the video skipped over the

company.users.count

method and its behavior. Could you add that to the samples below?
Cheers,
-Andrew

635114?v=3&s=64
kobaltz said 3 months ago:

count will perform similar to size. However, for the life of the object (typically just the instance of the request), it will perform another Count(*) query. So, if you are getting the count of an object multiple times within a view or method of that instance, it would make multiple database calls.

length can actually be fast if you have already eager loaded the objects from the association. However, for the most part, I avoid length.

size is similar to count with the exception that it will "cache" the Count(*) query or perform it if necessary. It's basically like a memoization of the count.

11652222?v=3&s=64
scytherswings said 3 months ago:

I didn't realize that `.count` was so inefficient, looks like I have some optimization to do. Thanks for the information!

Login to Comment