1

我正在使用名为“bullet”的 gem 以避免 N + 1 问题。

我以前的代码是

@communities = Community.scoped.page(params[:page]).order("created_at DESC")

然后我收到了这个错误

N+1 Query detected
  Community => [:platform]
  Add to your finder: :include => [:platform]

N+1 Query detected
  Community => [:genre]
  Add to your finder: :include => [:genre]

N+1 Query detected
  Community => [:tags]
  Add to your finder: :include => [:tags]

然后显示一个包含超过 70 个 sql 的页面大约需要 650 毫秒。
所以我把它改成了这个

@communities = Community.scoped.page(params[:page]).per(10).order("created_at DESC").includes(:platform, :genre, :tags)

现在,子弹的警报消失了,但它需要 750ms 并且仍然有超过 70 条 sql。

这是为什么?

这是显示页面需要多长时间的结果(使用 rack-mini-profiler)

在此处输入图像描述

例如,每个大约需要 30mscommunities/_community 这可能是因为count

每个人都communities/_community调用这 2 个助手。莫非是这里sql数量多的原因?

def topic_button(community)
    last_post = community.community_topics.order('last_active_at DESC').first
    if last_post && last_post.last_active_at.today?
        link_to sanitize( "Topics ("+ community.community_topics.count.to_s+")" , community_community_topics_path(community)
    end
end


def uploader_button(community)
    last_post = community.community_uploaders.order('last_active_at DESC').first
    if last_post && last_post.last_active_at.today?
        link_to sanitize("Chat ("+ community.community_uploaders.count.to_s+")" , community_community_uploaders_path(community)
    end
end

更新

模型/社区.rb

paginates_per 10

控制器/communities_controller.rb

@communities = Community.scoped.page(params[:page]).order("created_at DESC")

/views/communities/index.html.erb

<span class='community'>
    <% @communities.each do |community| %>  
        <%= render 'communities/community', :community => community %>
    <% end %>
</span>

/views/communities/_community.html.erb

<div class="Box">
    <div class="List">
        <p class="name"><span><%= community.title %></span></p>
        <%= community.community_name %>
        <p class="img">
        <% if community.community_icon? %>
            <%= link_to image_tag(community.community_icon.url(:medium), :alt => community.title, :style => "width: 250px; height: 250px", :class => 'img-polaroid' ), community_path(community.community_name) %>
        <% end %>
        </p>
        <div class="link">
        <%= platform_search(community.platform.name, community.platform_id) %>
        <%= genre_search(community.genre.name, community.genre_id) %>
        </div>
        <div class="intro">
            <table>
                <tr>
                    <th>Member</th>
                    <td class="border"><%= link_to community.cached_votes_up.to_s , bookmarker_community_path(community.community_name) %></td>
                </tr>
                <tr>
                    <th>Publisher</th>
                    <td class="border"><%= link_to community.publisher, communities_path(:publisher => community.publisher) if !community.blank? %></td>
                </tr>
                <tr>
                    <th class="body">Body</th>
                    <td class="border"><%= community.body.slice(0,55) if !community.blank? %></td>
                </tr>
                <tr>
                    <th class="tag">Tags</th>
                    <td class="border">
                    <% community.tags.each do |tag| %>
                    <span><%= link_to tag.name, {:controller=>'communities', :action=>'index', :tag=>tag.name} %></span>
                    <% end %>
                    </td>
                </tr>
            </table>              
        </div>
        <div class="button">
            <%= topic_button(community) %>
            <%= uploader_button(community) %>
        </div>
        <div class="button">
            <%= chat_button(community) %>
            <%= link_to sanitize('Codes ( ' + community.codes_count.to_s + ' )', community_codes_path(community), :class => 'btn' %>
        </div>
        <div class="follow">
            <span class="bookmark_community" community-id="<%= community.id %>">
            <%= render :partial => "communities/bookmark", :locals => {:community => community} %>
            </span>
        </div>      
    </div>
</div>

application_helper.rb

def topic_button(community)
    last_post = community.community_topics.order('last_active_at DESC').first
    if last_post && last_post.last_active_at.today?
        link_to sanitize("Forum ("+ community.community_topics.count.to_s+")" , community_community_topics_path(community), :class => 'red_button'
    else
        link_to sanitize( "Forum ("+ community.community_topics.count.to_s+")" , community_community_topics_path(community), :class => 'button'
    end
end

def uploader_button(community)
    last_post = community.community_uploaders.order('last_active_at DESC').first
    if last_post && last_post.last_active_at.today?
        link_to sanitize("Uploader ("+ community.community_uploaders.count.to_s+")" , community_community_uploaders_path(community), :class => 'red_button'
    else
        link_to sanitize("Uploader ("+ community.community_uploaders.count.to_s+")" , community_community_uploaders_path(community), :class => 'button'
    end
end

def chat_button(community)
    if !community.comment_threads.last.nil? && community.comment_threads.last.created_at.to_date == Date.current.to_date
        link_to sanitize('Chat', chat_community_path(community), :class => 'red_button'
    else
        link_to sanitize('Chat', chat_community_path(community), :class => 'button'
    end
end

/views/communities/_bookmark.html.erb

<% if user_signed_in? %>
    <% if current_user.voted_up_on? community %>
        <%= link_to(bookmark_community_path(community), :remote => true, :class => 'button') do %>
            <i class="icon-remove"></i>
            Un-Bookmark
        <% end %>
    <% else %>
        <%= link_to(bookmark_community_path(community) ,:remote => true, :class => 'blue_button') do %>
            <i class="icon-bookmark"></i>
            Bookmark
        <% end %>
    <% end %>
<% else %>
    <%= link_to(bookmark_community_path(community) , :class => 'blue_button') do %>
        <i class="icon-bookmark"></i>
        Bookmark
    <% end %>
<% end %>
4

2 回答 2

1

我建议您查看您的开发日志。您肯定会发现哪个过程或部分花费了多少时间。首先清除您的开发日志。然后刷新您的页面/操作。

另一个建议是为 current_user、user_signed_in 等方法使用类变量?. 这些被执行了很多次。

@current_user = current_user

然后无需在任何地方使用 current_user 。只需将其替换为@current_user。在你的 development.log 中你会发现不同之处。

同样,为了提高速度,您可以使用缓存。

于 2013-07-18T06:46:48.107 回答
1

为了获得更好的性能,请从表中选择所需的字段/列。

它将节省用于每个请求的系统内存,并节省从数据库中获取它们的时间。

如果您使用的是 rails3,请使用“select”方法,或者您可以在 rails2 的 find 方法中使用“select”选项。

如果您使用内存对象缓存系统,则不应选择特定字段。

于 2013-07-18T08:05:48.050 回答