如何有效地从Rails中的一个巨大的表中获取所有行?

时间:2016-05-03 06:30:36

标签: mysql ruby-on-rails ruby activerecord

我有两个表sh -xusers,用户记录超过50k,笔记记录为90k。

notes

users_table架构:

class User < ActiveRecord::Base
  has_many :notes
end

notes_table的架构:

id  email  created_at

我正在尝试创建一个临时表id user_id created_at category impact_score ,它可以包含两个表的数据,我可以在其中执行ActiveRecord查询来获取数据。

user_notes_table的架构:

temp_user_notes

我这样做

id  user_id  notes_id  email user_created_at notes_created_at category impact_score

循环使用所有用途和他们的笔记是非常长的记忆进食过程我可以使用其他方法吗?

编辑从这里: -

我的要求是:我有一系列由AND和OR条件分隔的查询,它们使用下表:用户,备注,交易,订阅。假设我的目标用户查询是def self.populate_temp_user_notes users = User.all users.each do |user| user.notes.each do |note| user_notes = TempUserNote.new user_notes.user_id = user.id user_notes.notes_id = note.id user_notes.auth_token_created_at = user.auth_token_created_at user_notes.notes_recorded_at = note.recorded_at user_notes.category = note.category user_notes.well_being_score = note.perception_score user_notes.save end end end 然后输出每个查询输入下一个查询。

例如:

(Query1 OR Query2) AND Query3 AND Query4

在最后一个用户列表中,我有我的目标用户和备注。

3 个答案:

答案 0 :(得分:3)

我会使用find_eachincludes的组合来减少内存使用量和数据库查询数量:

def self.populate_temp_user_notes
  User.includes(:notes).find_each do |user|
    user.notes.each do |note|
      TempUserNote.create(
        user_id:               user.id,
        notes_id:              note.id,
        auth_token_created_at: user.auth_token_created_at,
        notes_recorded_at:     note.recorded_at,
        category:              note.category,
        well_being_score:      note.perception_score,
      )
    end
  end
end

另一个非常快的选择可能是在这样的普通SQL中执行此操作:

INSERT INTO temp_user_notes
  (user_id, notes_id, auth_token_created_at, notes_recorded_at, category, well_being_score)
  SELECT users.id, notes.id, users.auth_token_created_at, notes.recorded_at, notes.category, notes.perception_score
    FROM users INNER JOIN notes ON users.id = notes.user_id;

答案 1 :(得分:1)

使用大量数据,使用User.all永远不会有益。想象一下,提取50k行数据,然后为每一行创建一个User类的全新对象,并用该行中的数据填充该对象。是的,它会给你带来麻烦,Rails也会意识到这一点。

您可以使用:

User.find_each do |user|
  # do your thing
end

find_each将一次为您提供1000条记录,从而减少内存操作。

您可以在batch_size中提供find_each来覆盖默认值:

User.find_each(batch_size: 3000) do |user|
  # do your thing
end

答案 2 :(得分:0)

我正在尝试创建一个临时表temp_user_notes,它可以包含两个表的数据,我可以在其中执行ActiveRecord查询来获取数据。

更简单的方法是加入两个表。如果您使用以下条款:

User.joins(:notes)

然后这将为您提供可用于进一步查询的范围(您可以在两个表上添加where条件),并且返回的记录将包括User和{{ 1}}模型,例如:

Note

将为您提供具有足够高分的所有笔记及其附加用户。

如果您需要浏览所有已连接的记录,则应使用批量返回记录的find_each method