2011-12-27 56 views
0

我在使用Rails應用程序的其中一個頁面時遇到了一些相當慢的加載時間。我試圖提高績效方面取得了一些進展,但並未達到我所希望的水平。我想知道如果我是在做一件愚蠢的事情來讓自己產生這種悲傷,或者如果有人能夠給我提供建議以更好地優化我的模型/遷移/查詢/視圖。我正在運行Rails 3.1並使用PostgreSQL。這是我到目前爲止已經試過:提高查詢/查看加載時間[Ruby on Rails]

  • 添加包括(:項目=>:類)控制器的查詢,是企圖獲取預先所有ItemCategories,而不是運行其他查詢時outfits_helper要求他們。
  • 渲染泛音作爲集合,而不是通過列/關係手動
  • 添加索引迭代到正在由有問題的控制器動作/視圖訪問
    • 衣服表表:索引USER_ID和CATEGORY_ID
    • 項表:索引USER_ID和CATEGORY_ID
    • outfit_items表:索引ITEM_ID,outfit_id和[outfit_id,ITEM_ID]

下面是我的代碼的相關部分:

控制器

# outfits_controller.rb 

NUM_OUTFITS_PER_PAGE = 8 

def other_users_outfits 
    # using Kaminari for pagination 
    @outfits = Outfit.does_not_belong_to_user(current_user).in_category_with_id(category_id).includes(:items => :category).page(params[:page]).per(NUM_OUTFITS_PER_PAGE) 
end 

模型

# outfit.rb 

has_many :items, :through => :outfit_items 
belongs_to :category, :class_name => 'OutfitCategory' 

scope :does_not_belong_to_user, proc {|user| where('user_id != ?', user.id) } 

scope :in_category_with_id, proc {|cat_id| 
    if cat_id.blank? 
    scoped 
    else 
    where(:category_id => cat_id) 
    end 
} 

# outfit_item.rb 

belongs_to :item 
belongs_to :outfit 

# item.rb 

has_many :outfit_items 
has_many :outfits, :through => :outfit_items 
belongs_to :category, :class_name => 'ItemCategory' 

# item_category.rb 

has_many :items, :foreign_key => 'category_id' 

outfit_category.rb 

has_many :outfits, :foreign_key => 'outfit_id' 

遷移

# create_outfits.rb 

def self.up 
    create_table :outfits do |t| 
    t.column :category_id, :integer 
    t.column :user_id, :integer 
    t.timestamps 
    end 

    add_index :outfits, :category_id 
    add_index :outfits, :user_id 
end 

# create_outfit_items.rb 

def self.up 
    create_table :outfit_items, :id => false do |t| 
    t.column :item_id, :integer 
    t.column :outfit_id, :integer 
    t.timestamps 
    end 

    add_index :outfit_items, :item_id 
    add_index :outfit_items, :outfit_id 
    add_index :outfit_items, [:outfit_id, :item_id] 
end 

# create_items.rb 

def self.up 
    create_table :items do |t| 
    t.column :category_id, :integer 
    t.column :user_id, :integer 
    t.timestamps 
    end 

    add_index :items, :category_id 
    add_index :items, :user_id 
end 

# create_item_categories.rb 
def self.up 
    create_table :item_categories do |t| 
    t.column :name, :string 
    t.column :category_type, :string 
    t.timestamps 
    end 
end 

# create_outfit_categories.rb 

def self.up 
    create_table :outfit_categories do |t| 
    t.column :name, :string, :limit => 100, :null => false 
    t.timestamps 
    end 
end 

查看

# other_users_outfits.html.haml 

= render :partial => 'other_users_outfit', :collection => outfits, :as => :outfit 

# _other_users_outfit.html.haml 

.outfit 
    .primary-items 
    = render :partial => 'other_users_outfit_primary_item', :collection => primary_outfit_items_top_to_bottom(outfit), :as => :item 
    .secondary-items 
    = render :partial => 'other_users_outfit_secondary_item', :collection => secondary_outfit_items(outfit), :as => :item 

# _other_users_outfit_primary_item.html.haml 

= image_tag item.image_url(:outfit_item), :class => 'primary-outfit-item' 

# _other_users_outfit_secondary_item.html.haml 

= image_tag item.image_url(:baby_thumb), :class => 'secondary-outfit-item' 

助手
# outfits_helper.rb 

def primary_outfit_items_top_to_bottom(outfit) 
    primary_items = [] 
    primary_items.push(outfit_item_in_category(outfit, 'Tops')) 
    primary_items.push(outfit_item_in_category(outfit, 'Full-lengths')) 
    primary_items.push(outfit_item_in_category(outfit, 'Bottoms')) 
    primary_items.push(outfit_item_in_category(outfit, 'Footwear')) 
    primary_items.compact 
end 

def secondary_outfit_items(outfit) 
    outfit.items.select{|item| item.category.category_type == 'secondary' } 
end 

def outfit_item_in_category(outfit, cat_name) 
    outfit.items.select{|item| item.category.name == cat_name }.first 
end 

控制檯輸出

User Load (1.0ms) SELECT DISTINCT users.id, users.* FROM "users" WHERE "users"."id" = 3 LIMIT 1 
(0.5ms) SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "outfits" WHERE (user_id != 3) LIMIT 8 OFFSET 0) subquery_for_count 

Outfit Load (0.7ms) SELECT DISTINCT outfits.id, outfits.* FROM "outfits" WHERE (user_id != 3) ORDER BY outfits.created_at DESC LIMIT 8 OFFSET 0 

OutfitItem Load (0.6ms) SELECT "outfit_items".* FROM "outfit_items" WHERE "outfit_items"."outfit_id" IN (28, 27, 26, 25, 24, 23, 22, 21) 

Item Load (2.2ms) SELECT DISTINCT items.id, items.*, "items".* FROM "items" WHERE "items"."id" IN (18, 20, 23, 7, 6, 30, 4, 1, 17, 5, 15, 12, 9, 29, 10, 19, 3, 8, 13) ORDER BY items.created_at DESC 

ItemCategory Load (0.5ms) SELECT "item_categories".* FROM "item_categories" WHERE "item_categories"."id" IN (4, 6, 2, 1, 3, 7) 

Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.2ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.1ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.8ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.4ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.9ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (1.2ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.9ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.7ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.8ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.7ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (1.2ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (1.1ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.2ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.8ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (3.4ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.0ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.6ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_secondary_item.html.haml (0.3ms) 
Rendered outfits/_other_users_outfit_primary_item.html.haml (2.1ms) 
Rendered outfits/_other_users_outfit.html.haml (56.3ms) 
    (0.5ms) SELECT COUNT(*) FROM "outfits" WHERE (user_id != 3) 
Rendered outfits/other_users.html.haml within layouts/application (2073.5ms) 

Role Load (0.4ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = 'admin' LIMIT 1 
    (0.4ms) SELECT 1 FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 3 AND "roles"."id" = 1 LIMIT 1 

Rendered layouts/_top_nav.html.haml (1.0ms) 
    (0.6ms) SELECT COUNT(*) FROM "items" WHERE "items"."user_id" = 3 

Rendered layouts/_points_display.html.haml (5.7ms) 

Outfit Load (0.6ms) SELECT DISTINCT outfits.id, outfits.* FROM "outfits" WHERE "outfits"."user_id" = 3 ORDER BY outfits.created_at DESC 

OutfitCategory Load (0.3ms) SELECT "outfit_categories".* FROM "outfit_categories" 

任何幫助將不勝感激!

+0

它是否在生產或開發環境? – 2011-12-27 17:36:32

+0

它在生產中更糟,但仍比開發中的所有其他視圖慢得多。 – 2011-12-29 15:14:20

回答

0

我看到的唯一能改善的地方就是幫手中的代碼。是否有這樣做的原因:

def outfit_item_in_category(outfit, cat_name) 
    outfit.items.select{|item| item.category.name == cat_name }.first 
end 

而不是將此代碼推送到項目模型中的作用域?如果你有很多項目,你基本上是在做一個SELECT *,然後用Ruby進行過濾。

+0

我使用這個幫助器方法的原因,與在Item模型中使用範圍相反,是因爲1)我實際上需要視圖中的所有項和2),因爲排序算法有點任意性「,我不相信我可以在模型範圍內處理它,除非我添加了一個列,其唯一目的是提供一種方法爲這個特定視圖分類項目。 – 2011-12-29 15:07:37