Question

I have a user profile page that has a sidebar with user stats like not unlike the Stack Overflow profile page (e.g., total visits, number of badges).

The trouble is that currently I'm hitting the database and calculating these stats with every single request. I can implement fragment caching to cut down on this, but is there a better way to handle this type of thing?

Storing the aggregated summary data in the database seems like it might lead to problems (i.e., inconsistency).

Was it helpful?

Solution

You could store this information in the database instead of recalculating it, using:

  1. Counter caching
  2. Custom callbacks

Counter Caching

As an example, if measuring the number of badges, you could create a database field in User called badges_count, then in the Badge model, have belongs_to :user, :counter_cache => true. Now, whenever the number of badges changes, you can access the count without any new calculations at @user.badges_count.

A basic implementation: http://asciicasts.com/episodes/23-counter-cache-column

Custom Callbacks

Let's say you have a field that measures behavior that is more complex than a simple count. In this case, just implement callbacks that update a field whenever a certain action occurs using before_save, after_save, before_create, etc.

Concerns about Inconsistency

Storing the data in your database will only be inconsistent if you're doing it wrong. There are a finite number of paths through which any statistic can be updated, and you should ensure that all paths are covered in updating whichever field you are using. Rails does it for you with counter_caching, and you have to do it yourself if you use custom callbacks or you have some unusual situation.

OTHER TIPS

You could use a hidden div like in this question (Caching data by using hidden divs). Depending on how much data you want to cache this might be a good solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top