Rails选择每组前n条记录(内存泄漏)

时间:2017-09-08 18:22:54

标签: mysql ruby-on-rails

我有这个方法,使用find_by_sql返回每个来源的10条最新记录

def latest_results
    Entry.find_by_sql(["
    select x.id,x.created_at,x.updated_at,x.source_id,x.`data`,x.`uuid`,x.source_entry_id
    from
      (select t.*,
        (@num:=if(@group = `source_id`, @num +1, if(@group := `source_id`, 1, 1))) row_number
          from (
      select d.id,d.created_at,d.updated_at,d.source_id,d.`data`,d.`uuid`,d.source_entry_id
      from `streams` a
      JOIN `stream_filters` b
      on b.stream_id=a.id
      JOIN `filter_results` c
      on c.filter_id=b.id
      JOIN `entries` d
      on d.id=c.entry_id
      where a.id=?
        ) t
      order by `source_id`,created_at desc
      ) as x
      where x.row_number <= 10
      ORDER BY x.created_at DESC
    ",self.id])
  end

它在有限记录的本地环境中正常工作。 我有t2.micro,它有2个Gib内存来服务应用程序。现在这个查询耗尽我的整个记忆和应用程序得到frizzing。 任何建议我怎样才能做得更好?我想在不增加机器尺寸的情况下解决这个问题。

1 个答案:

答案 0 :(得分:1)

我曾遇到过类似的问题。尽管很难优化,但mysql变量的解决方案看起来很整洁。在您的情况下,似乎正在进行全表扫描。

我建议您首先获取要显示的来源。然后运行第二个查询,其中包含多个前10个选项,每个源一个,所有都与联合组合。

联合前10名选择将有一些重复声明,您可以使用ruby轻松自动生成。

# pseudo code
sources = Entry.group(:source).limit(n)
sql = sources.map do |source|
   "select * from entries where source = #{source} order by created_at limit 10"
end.join("\nunion all\n")

Entry.find_by_sql(sql)