我有两种情况需要很长时间才能加载页面,而且我不知道如何在最近开始使用RoR时更快地调用数据库.
案例A.
我试图显示根类别(使用祖先宝石)和与这些根类别相关联的供应商数量.共有15个根类别.
结果如下:
>时尚(14)
>汽车(26)
> ……
suppliers.html.erb
<% Category.roots.each do |category| %>
<li class="pointer txt-hover-grey mili-margin-bottom">
<span class="micro-margin-right">
<%= link_to category.name, category_suppliers_path(category), :title => category.name %>
</span>
<span class="txt-alt">
(<%= category.suppliers_count_active %>)
</span>
</li>
<% end %>
category.rb
def suppliers_count_active
self.suppliers.where(:active => true).pluck(:id).count
end
案例B(祖先宝石)
这与主要类别菜单有关(就像您可以在任何电子商店中找到的那样).有15个根类别(级别0),然后每个根类别有3个子类别(总共45个),每个子类别有大约5个子子类别(总共大约225个).对于每个子子类别,我也填充该类别中的产品数量.
结果如下:
>时尚
>男士们
> T恤(34555)
>内衣(14555)
> ……
>女人
> T恤(43000)
>内衣(23000)
>运动
>单板滑雪
> XYT(2323)
> ……
> ……
> ……
categories_menu.html.erb
<div class="content no-padding padding-static relative table menu-nr">
<!-- root_categories -->
<% Category.includes(:image, :products).serializable.each do |root| %>
<div class="table-center container-center full-h categories-trigger">
<%= link_to Category.find(root['id']).category_link, :title => root['name'] do %>
<div class="uppercase full-h size-tiny semi-bold txt-hover-main_light semi-padding-top semi-padding-bottom">
<%= root['name'] %>
</div>
<% end %>
<div class="categories-hide categories-dropdown shadow z-1000 bg-white txt-black size-tiny">
<div class="table full-w inwrap-dropdown">
<div class="cell">
<div class="table dropdown-left">
<%
children_sorted = root['children'].sort_by { |child| child['products_sum_count'] }.reverse!.first(3)
children_sorted.each do |cat| %>
<div class="cell container-left">
<div class="table">
<div class="cell container-top">
<div class="mili-margin-left mili-margin-right">
<% cat2 = Category.find_by(:id => cat['id'])
if !cat2.image.blank? %>
<%= image_tag(cat2.image.image.url(:small), :title => cat2.image.title, :alt => cat2.image.title, :class => "img-category") %>
<% end %>
</div>
</div>
<div class="cell">
<h5 class="mili-margin-bottom">
<%= link_to "#{cat['name']}", Category.find(cat['id']).category_link, :title => cat['name'] %>
</h5>
<div class="txt-grey_dark semi_bold mili-margin-bottom">
<%
# cat_children = cat.children.includes(:products)
cat['children'].first(7).each do |sub_cat|
%>
<%= link_to Category.find(sub_cat['id']).category_link, :title => sub_cat['name'], :class => "block txt-hover-grey micro-margin-bottom" do %>
<%= "#{sub_cat['name']}" %> <span class="txt-alt"><%= "(#{sub_cat['products_sum_count']})" %></span>
<% end %>
<% end %>
</div>
<%= link_to "Další kategorie >", Category.find(cat['id']).category_link, :class => "semi-margin-top block txt-alt txt-hover-alt_dark" %>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="cell bg-grey_light semi-padding-left">
<div class="table">
<div class="cell container-left">
<div class="mili-margin-left mili-margin-right">
<h5 class="txt-alt mili-margin-bottom">
<%= t(:menu_suppliers_title) %>
</h5>
<%
suppliers = Supplier.joins(:categories).where(:active => true, categories: { :id => root['id'] }).last(3)
suppliers.each do |supplier|
%>
<% cache supplier do %>
<div class="table relative mili-margin-bottom">
<div class="cell inline relative wrap-shop">
<div class="absolute-center-nr center inwrap-shop inwrap-shop-rohlik btn border">
<%= link_to supplier_path(supplier), :title => "#{t(:menu_suppliers_link_title)} #{supplier.name}" do %>
<%= image_tag(supplier.image.image.url(:small), :alt => supplier.image.title) if !supplier.image.blank? %>
<% end %>
</div>
</div>
<div class="col inline semi-margin-left-nr">
<div class="table txt-avatar-small full-w">
<div class="table-center">
<%= link_to supplier.name, supplier_path(supplier), :title => "#{t(:menu_suppliers_link_title)} #{supplier.name}", :class => "semi-bold block micro-margin-bottom" %>
<div class="txt-alt">
<%= t(:homepage_suppliers_logo_text, :commission => supplier.commission_donated, :commission_type => supplier.commission_type ) %>
</div>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
<span class="block txt-alt txt-hover-alt_dark half-margin-bottom">
</span>
<%#= link_to t(:menu_suppliers_link_others), category_suppliers_path(:id => root['id']), :title => t(:menu_suppliers_link_others), :class => "block txt-alt txt-hover-alt_dark half-margin-bottom" %>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="categories-hide wrap-categories-arrow relative">
<div class="categories-arrow absolute z-1000">
</div>
</div>
</div>
<% end %>
</div>
category.rb
def self.serializable
Category.includes(:translations).where(categories: {:active => true, :ancestry_depth => 0..2 }, category_translations: {:locale => I18n.locale.to_s} ).arrange_serializable(:order => 'category_translations.name')
end
def category_link
category_path(self)
end
这两种情况都需要几秒钟才能加载.任何建议真的很感激.
谢谢,
米罗斯拉夫
更新1:
在这里,您可以看到NewRelic的输出.在尝试实现dalli memcache和identity_cache之后,它与案例B有关.我还上传了菜单的屏幕截图.
> NewRelic Output
> Menu
更新2:
最耗时的部分似乎是以下代码:
result = Benchmark.ms { Category.includes(:translations).where(categories: {:active => true, :ancestry_depth => 0..2 }, category_translations: {:locale => I18n.locale.to_s} ).arrange_serializable(:order => 'category_translations.name') }
=> 7207.116272300482
它生成层次结构中所有活动类别(大约1000)的哈希值,因此我可以为菜单正确呈现它.
不确定如何优化这部分.
更新3
我使用postgres数据库.
CategoryTranslation表
create_table "category_translations", force: :cascade do |t|
t.integer "category_id", null: false
t.string "locale", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
add_index "category_translations", ["category_id"], name: "index_category_translations_on_category_id", using: :btree
add_index "category_translations", ["locale"], name: "index_category_translations_on_locale", using: :btree
分类表
create_table "categories", force: :cascade do |t|
t.string "name"
t.boolean "active", default: false
t.integer "level"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ancestry"
t.string "mapping"
t.integer "products_count", default: 0, null: false
t.integer "products_sum_count", default: 0
t.integer "ancestry_depth", default: 0
t.string "category_link"
t.string "image_link"
end
add_index "categories", ["ancestry"], name: "index_categories_on_ancestry", using: :btree
最佳答案 案例A.
这里最好的做法是在类别模型中缓存活动供应商的计数.
>在Category模型中添加active_supliers_count列
>将after_save挂钩添加到供应商模型,并在其变为活动/非活动时递增/递减类别的计数器
案例B
这里的问题与案例A中的问题相同,您需要添加缓存计数器.
看来你在循环中创建了多个包含.您可以只使用所需的一切.
例如
Category.includes(children: [:image, :products])