从大约100k行用户表和15000k行得分表数据库中,我可以通过哪些方式加快总分计算?我已经在score表中添加了user_id的索引。 现在,速度是: 呈现的用户/ _user_row.html.erb(3.0ms) 在布局/应用程序中呈现users / index.html.erb(1970.1ms) 在2113ms完成200 OK(浏览次数:343.8ms | ActiveRecord:1768.3ms)
我拥有的是
User_controller:
def index
@users = User.by_total_points.limit(50)
end
User.rb型号:
has_many :points
def self.by_total_points
joins(:points).group('users.id').order('SUM(points.value) DESC')
end
def total_points
self.points.sum(:value)
end
point.rb模型:
belongs_to :user
Schema.rb
create_table "points", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "value", null: false
t.string "label", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "points", ["user_id"], name: "index_points_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "first_name", null: false
t.string "last_name", null: false
t.string "username", limit: 32, null: false
t.string "email", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "sumscore"
end
答案 0 :(得分:0)
所以这不是一个Rails问题,更多的是系统设计问题。如果你只是想要获得前50名,你可以
这样,你就可以在50条记录上插入nlog(n)的时间,它是渐近渐变的。
在这个系统中,你将有两个scroing表,或一个表,一个redis数组。主表保留所有分数,缓存表或数组只保持前50名。
如果您尝试获得所有排名,您可以将排序树(n-nary)和存储桶用户构建为得分范围,以便您执行log(n)插入和读取。设置有点复杂,我建议避免使用它,除非你每秒有数百个写入更新分数,而你的应用需要实时排名,而且你有超过1亿用户。
答案 1 :(得分:0)
很多答案都是关于它被击中的频率,点数更新的频率以及分数过时的可能性。
您最终可能会使用缓存或计数器。只是随意刺伤它而没有任何背景
现在,您可以检查缓存,而不是点击数据库,您的请求现在可以快速点亮,但需要花费额外的工作来更新缓存。
http://guides.rubyonrails.org/caching_with_rails.html
额外注意:在丢失缓存时,还要编写一个rake任务来重建这些任务。