0

私は現在、イベント サイトをハッキングしており、クエリの最適化やデータベースのスケーリングで問題が発生したことは一度もありません。これは、それほど多くのデータがなかったためです。イベントのフィード、特に部分 (各 _event.html.erb 内) をレンダリングするのは非常に遅く、現在フォローしているすべてのユーザーがそのイベントに参加している場所に表示されます。熱心な読み込み、インデックス作成、memcache など、パフォーマンスを改善するための多くの可能性を調べましたが、これを書き直してより高速に実行するにはどうすればよいでしょうか? ありがとうございました!

_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 %>

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"

関係のスキーマ

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"

ユーザーモデルの関連部分

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
4

2 に答える 2

0

大規模データベースが RSVP の場合:

パーシャルで db に対して非常に大きな呼び出しを行い、n 呼び出しをRsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')1 回だけ減らしてから、さまざまなケースで作業します。これは、パフォーマンスを少し向上させることができます (大規模なデータベースがある場合、大規模なデータベースで .where を呼び出すたびに複雑なプロセスになります)。変数 @rsvp を再利用します。

于 2012-10-25T14:01:47.667 に答える
0

簡単なクリーンアップを行い、@damoiser が言ったことに従うだけで、ビューを次のようにリファクタリングする必要があります。

_attending.html.erb

<% if user_signed_in? %>
  <% @rsvp = get_rsvps %>
  <% if @rsvp.count == 0 %>
    <%= eventcount(event) %> going.
  <% elsif @rsvp.count == 1 %>
    <% if eventcount(event) - 1 == 0 %>
      <% @rsvp[0..0].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> is going.
      <% end %>
    <% else %>
      <% @rsvp[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[0..0].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> and
      <% end %>
      <% @rsvp[1..1].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> are going.
      <% end %>
    <% else %>
      <% @rsvp[0..0].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
      <% end %>
      <% @rsvp[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[0..0].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
      <% end %>
      <% @rsvp[1..1].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>, and
      <% end %>
      <% @rsvp[2..2].each do |f| %>
          <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %> are going.
      <% end %>
    <% else %>
      <% @rsvp[0..0].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
      <% end %>
      <% @rsvp[1..1].each do |f| %>
        <%= link_to User.find(f.voter_id).name, User.find(f.voter_id).slug %>,
      <% end %>
      <% @rsvp[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 %>

次のようなヘルパーも必要です。

some_helper.rb

module SomeHelper
  def get_rsvps
    Rsvp.where(:voter_id => current_user.following, :event_id => event.id, :status => 'going')
  end
end 

巨大な注意:このコードはまだうまくいくわけではありません。まだまだリファクタリングしなければならないことがたくさんあると思います。[0..0].each と [1..1].each のように、link_to ヘルパーの多くのコードが重複しています。ただし、rsvp の呼び出しを行い、@rsvp に保存したものを再利用するだけなので、これによりパフォーマンスが向上するはずです。

于 2012-10-25T14:21:57.587 に答える