簡體   English   中英

提高 Rails model 的性能

[英]Improving performance of Rails model

我有以下 model 允許用戶在照片上投票。

class Vote < ActiveRecord::Base
    attr_accessible :value

    belongs_to :photo
    belongs_to :user

    validates_associated :photo, :user
    validates_uniqueness_of :user_id, :scope => :photo_id
    validates_uniqueness_of :photo_id, :scope => :user_id
    validates_inclusion_of :value, :in => [-2,-1,1,2], :allow_nil => true

    after_save :write_photo_data

    def self.score
        dd = where( :value => -2 ).count
        d = where( :value => -1 ).count
        u = where( :value => 1 ).count
        uu = where( :value => 2 ).count
        self.compute_score(dd,d,u,uu)
    end

    def self.compute_score(dd, d, u, uu)
        tot = [dd,d,u,uu].sum.to_f
        score = [-5*dd, -2*d, 2*u, 5*uu].sum / [tot,4].sum*20.0
        score.round(2)
    end

    private
        def write_photo_data
            self.photo.score = self.photo.votes.score
            self.photo.save!
        end

end

這個功能非常好,但是計算一張照片的分數非常慢——平均需要 7-12 秒。 我嘗試為photo_iduser_id添加索引,以及為photo_idvalue添加一個索引,但據我所知,這並沒有真正提高性能。

我會對任何認真的 Rails 專家(我完全是個業余愛好者)關於如何優化/改進的反饋感興趣。 您將如何計算對特定照片和價值的投票?

謝謝!

- 編輯 -

請注意,分數: -2,-1,1,2表示“兩個拇指向下,一個拇指向下,一個拇指向上,兩個拇指向上”,而不是具體值。 我可以將這些與我在計算分數方法中分配給它們的值相匹配,但到目前為止我還沒有這樣做,因為我可能希望在看到更多數據積累后隨着時間的推移調整權重。

此外,無論我如何在數據庫中表示這四個可能的投票,我仍然需要每種投票的 COUNT 以及每張照片的這些投票的加權值來計算分數。 謝謝!

您可以做的一件事是向數據庫詢問一次而不是四次來獲取分數:

Vote.where(photo_id: photo.id).group(:value).count

將導致單個數據庫查詢並為您提供 hash 之類的

{-2 => 21, -1 => 48, 1 => 103, 2 => 84}

除此之外,如果您在數據庫中存儲[-5, -2, 2, 5]而不是[-2, -1, 1, 2]的實際值,您可以這樣做

Vote.where(photo_id: photo.id).sum

並直接從數據庫中獲取總和(或者甚至使用avg來獲取平均值)

你需要一個價值索引,就其本身而言。 組合索引僅在查詢具有兩個組件時才起作用,從左側開始。 由於您的 where 子句沒有指定照片 ID,因此它沒有使用您的組合索引。

更新http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

為什么存儲 -2、2、1、2 而不是實際成績? 如果您存儲成績(例如 -5),您將能夠直接在 DB 中計算分數,而無需運行 4 個計數查詢。 這肯定是一個進步。

如果數據庫中有大量記錄,在值列上放置索引將加快 SELECT 的速度。

上面的帖子也提出了一些直接優化的好處。 但是,隨着您的數據庫擴展,所有這些方法最終都會失敗。 由於分數是派生值,您可以將其緩存在 Memcached、Redis 甚至 SQL 中,這將確保獲取分數隨着應用程序的增長在恆定時間內擴展。 您可以允許緩存過時並使用后台進程保持更新。 通過這樣做,您的計算 function 可以花費任意時間而不會影響用戶體驗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM