0

I'm working on a Ruby on Rails site.

In order to improve performance, I'd like to build up some caches of various stats so that in the future when displaying them, I only have to display the caches instead of pulling all database records to calculate those stats.

Example:

A model Users has_many Comments. I'd like to store into a user cache model how many comments they have. That way when I need to display the number of comments a user has made, it's only a simple query of the stats model. Every time a new comment is created or destroyed, it simply increments or decrements the counter.

How can I build these stats while the site is live? What I'm concerned about is that after I request the database to count the number of Comments a User has, but before it is able to execute the command to save it into stats, that user might sneak in and add another comment somewhere. This would increment the counter, but then by immediately overwritten by the other thread, resulting in incorrect stats being saved.

I'm familiar with the ActiveRecord transactions blocks, but as I understand it, those are to guarantee that all or none succeed as a whole, rather than to act as mutex protection for data on the database.

Is it basically necessary to take down the site for changes like these?

William Jones
  • 18,089
  • 17
  • 63
  • 98

3 Answers3

1

Your use case is already handled by rails. It's called counter cache. There is a rails cast here: http://railscasts.com/episodes/23-counter-cache-column

Since it is so old, it might be out of date. The general idea is there though.

Max
  • 15,157
  • 17
  • 82
  • 127
0

It's generally not a best practice to co-mingle application and reporting logic. Send your reporting data outside the application, either to another database, to log files that are read by daemons, or to some other API that handle the storage particulars.

If all that sounds like too much work then, you don't really want real time reporting. Assuming you have a backup of some sort (hot or cold) run the aggregations and generate the reports on the backup. That way it doesn't affect running application and you data shouldn't be more than 24 hours stale.

TCopple
  • 880
  • 7
  • 14
  • Could you explain your thoughts on this more? What are the key downsides and how bad do you think it is to be integrating application and reporting logic? This question on how to implement achievements has a highly-rated answer that appears to be exactly mixing application and reporting logic, and was how I was planning on implementing, with observers that increment the data after every save. http://stackoverflow.com/questions/885277/how-to-implement-an-achievement-system-in-ror – William Jones Apr 18 '12 at 21:24
0

FYI, I think I found the solution here:

http://guides.ruby.tw/rails3/active_record_querying.html#5

What I'm looking for is called pessimistic locking, and is addressed in 2.10.2.

William Jones
  • 18,089
  • 17
  • 63
  • 98