【问题标题】:Ruby on Rails Postgres/Active Record Search OptimizationRuby on Rails Postgres/Active Record 搜索优化
【发布时间】:2018-05-08 14:35:41
【问题描述】:

所以可能没有办法解决这个问题,但我想我会问:

我设置了一个 Postgresql 数据库。第一个表包含重放,每个重放都有 10 个独特的玩家(一个有很多关系)。我想根据我的搜索呈现一个 JSON,其中包含他们的播放器的回放。但是,我正在提取大量回放(2000 年)——它们都有 10 名玩家,这意味着搜索 20,000 名玩家。

这是索引搜索当前的样子:

def index
  @replays = Replay.where(map_id: params['map_id'].to_i)
  @replays = @replays.reverse
  render json: @replays[0..2000].to_json(include: [:players])
end

搜索需要这么长时间:

Completed 200 OK in 639596ms (Views: 42.1ms | ActiveRecord: 329252.3ms)

有没有更好的方法可以搜索和呈现不需要这么长时间的 JSON?值得注意的是,仅搜索 2k 回放、20k 玩家,甚至是单个特定玩家的回放只需要几秒钟(第一次搜索本身也只需要几秒钟),所以我认为这是一个数量问题。

【问题讨论】:

  • 你能贴出实际生成的sql查询吗?
  • 第一次搜索:SELECT "players".* FROM "players" WHERE "players"."replay_id" = $1 然后搜索players时:SELECT "players".* FROM "players" WHERE "玩家"."replay_id" = $1 [["replay_id", 117217]] (每次重播)

标签: ruby-on-rails json ruby postgresql


【解决方案1】:

尝试加载回放

replays = Replay.last_two_thousands_by_map_id(params[:map_id])

render json: replays.to_json(include: [:players])

# replay.rb model
def self.last_two_thousands_by_map_id(map_id)
  includes(:players).where(map_id: map_id).order(id: :desc).limit(2000)
end

【讨论】:

  • 这行得通,时间大大缩短了。在 254032 毫秒内完成 200 OK(查看次数:34.1 毫秒 | ActiveRecord:20682.4 毫秒)
  • 只是票 - 很好的答案。我要补充一点,值得将该请求的至少一些元素放入模型范围以稍微清理控制器。 @GustavMauler - 供将来参考,这是一个 N + 1 的问题,让你慢下来,docs here
  • 查询看起来仍然很大。如果需要,请打开另一个带有新瓶颈的问题。谢谢@SRack
  • 是的,我现在看到了。也许它很贪心,但是否有可能获得更好的性能?
  • 是的,我很确定。但是我们需要更多信息作为这个问题中的信息。打开另一个
猜你喜欢
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
相关资源
最近更新 更多