开发者

How to optimize my activity feed loop (Rails)

I am implementing an activity feed for my application, much like the facebook news feed. Whenever a user does something (creates a post, comments on a post, creates a photo album, comments on a photo) a row is created in an Activities table, which contains user_id, category, and data. Data is a serialized hash that is different for each type of activity (post contains post title and post id, photo comment contains something else, etc). The view then loops through all of the activities 开发者_如何学Pythonand prints something depending on the category of activity. Pretty simple, and it works. The problem is that it's SUPER slow, so I must be doing something wrong. Here's the code:

#activity.rb snippet

  def post?
   category == "post"
  end

  def post_comment?
   category == "post_comment"
  end

  def album?
   category == "album"
  end

  def photo_comment?
   category == "photo_comment"
  end

#controller snippet

@Activity = Activity.all(:order=> 'created_at DESC', :limit=>"5")

#view snippet

<% @Activity.each do |a| %>
 <div class="activity_item">
  <div class="avatar" style="background-image: url(<%= small_pic_url(a.user)%>) "></div>
  <div class="text"> <%= a.user.username %> 
  <% if a.post? %>
   posted <%= link_to a.data["post_title"], post_path(a.data["post_id"]) %>
  <% elsif a.post_comment? %>
   commented on <%= link_to a.data["post_title"], post_path(a.data["post_id"]) %>
  <% elsif a.album? %>
   created a <%= link_to "Photo Album", album_path(a.data["album_id"])%>
  <% elsif a.photo_comment? %>
   commented on <%= link_to "#{a.data["username"]}'s photo", upload_path(a.data["photo_id"])%>
  <% end %>
  </div>
 </div>
 <% end %>

I added a user_id index on the activity table, but that didn't seem to do much. Rendering the 5 activity items/avatars takes over 3 seconds, so there must be a better way to handle this.


Do you have an index on created_at? If you don't, that'll be what's slowing you down - MySQL will have to read through every row in your activities table to make sure it got the latest five (this applies to just about anything using an ORDER BY clause).

And a couple more suggestions, but these are minor. Might shave a few milliseconds off, but nothing on the order of three seconds:

  1. Include the user when you select your activities. This'll let you get your activities and their users in a single DB query. :include => :user should do the trick, or there's a Rails 3-style .include(...) method, if you prefer.
  2. I've heard that serialization can be kinda slow. Perhaps you could use a polymorphic association, and then choose what to display based on a.whatever_type?

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜