I’m currently hacking on an events site and have never had a problem optimizing queries/scaling my db in the past as there was never that much data, but now there’s almost a million rows in the db and it’s taking ~15,000 m/s to render a feed of events, in particular the partial (within each _event.html.erb) that’s really slow is where all the users that youre currently following that are attending that event are displayed. I’ve looked up a lot of possibilities to improve performance including eager loading, indexing, memcache, etc…but was wondering how this can be rewritten to perform faster? Thank you!
_attending.html.erb
<% if user_signed_in? %>
<% @rsvp = Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going') %>
<% if @rsvp.count == 0 %>
<%= eventcount(event) %> going.
<% elsif @rsvp.count == 1 %>
<% if eventcount(event) - 1 == 0 %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> is going.
<% end %>
<% else %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> and <%= eventcount(event) - 1 %> going.
<% end %>
<% end %>
<% elsif @rsvp.count == 2 %>
<% if eventcount(event) - 2 == 0 %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> and
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[1..1].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> are going.
<% end %>
<% else %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[1..1].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> and <%= eventcount(event) - 2 %> going.
<% end %>
<% end %>
<% elsif @rsvp.count == 3 %>
<% if eventcount(event) - 3 == 0 %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[1..1].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>, and
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[2..2].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> are going.
<% end %>
<% else %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[0..0].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[1..1].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
<% end %>
<% Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')[2..2].each do |f| %>
<%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> and <%= eventcount(event) - 3 %> are going.
<% end %>
<% end %>
<% end %>
<% else %>
<%= eventcount(event) %> going.
<% end %>
Schema for RSVP
create_table "rsvps", :force => true do |t|
t.string "status"
t.integer "event_id"
t.integer "voter_id"
t.string "voter_name"
t.string "voter_type"
t.timestamp "created_at", :null => false
t.timestamp "updated_at", :null => false
end
add_index "rsvps", ["voter_id", "voter_type", "event_id"], :name => "fk_one_rsvp_per_user_per_entity", :unique => true
add_index "rsvps", ["voter_id", "voter_type"], :name => "index_rsvps_on_voter_id_and_voter_type"
Schema for Relationship
create_table "relationships", :force => true do |t|
t.integer "follower_id"
t.integer "followed_id"
t.timestamp "created_at", :null => false
t.timestamp "updated_at", :null => false
end
add_index "relationships", ["followed_id"], :name => "index_relationships_on_followed_id"
add_index "relationships", ["follower_id"], :name => "index_relationships_on_follower_id"
Relevant part of User model
has_many :relationships, :foreign_key => "follower_id",
:dependent => :destroy
has_many :following, :through => :relationships, :source => :followed
has_many :reverse_relationships, :foreign_key => "followed_id",
:class_name => "Relationship",
:dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
If the large db is the RSVP:
You do a very large call to the db in your partial, try to reduce the n call
Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')only one time, and then working on it in the different cases. This can help a little in performance (every time you call a .where in large db is a complex process if you have a large db). Re-use the variable @rsvp.