Ruby on rails Rails ActiveRecord原始sql读取数据,无需将所有内容加载到内存中(无分页)

Ruby on rails Rails ActiveRecord原始sql读取数据,无需将所有内容加载到内存中(无分页),ruby-on-rails,activerecord,Ruby On Rails,Activerecord,.NET具有SqlDataReader: using(SqlDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { var myString = rdr.GetString(0); // ... } } 我需要将原始sql与Rails和ActiveRecord(现有项目,无法添加任何gems)一起使用 我现在能做的就是: ActiveRecord::Base.connect

.NET具有SqlDataReader:

using(SqlDataReader rdr = cmd.ExecuteReader())
{
    while (rdr.Read())
    {
        var myString = rdr.GetString(0);
        // ...
    }
}
我需要将原始sql与Rails和ActiveRecord(现有项目,无法添加任何gems)一起使用

我现在能做的就是:

ActiveRecord::Base.connection.exec_query(query)
它可以工作,但对于我的
选择…
会将所有行加载到内存中。我真的希望在不将结果加载到内存的情况下遍历结果,就像在.NET中一样

使用Ruby/Rails/ActiveRecord可以吗


我知道分页,只是想知道还有没有别的方法?

你可以考虑使用<代码> FordPyAuth/<代码>。默认批量大小为1000,但您可以将该选项传递为您喜欢的任何值


如果不想实例化每个对象,您可能会发现另一个有用的方法是
pull

,它可能取决于用例。如果您想坚持使用
的轨道方式,请按建议查找每个

由于您的问题表明您对较低级别的修改和速度感兴趣,我想提出另一个选项,因为实例化ActiveRecord模型可能会有相当大的开销

写一个包装并不难

ActiveRecord::Base.connection.exec_query(query)
其行为类似于您提到的
SqlDataReader

class SqlDataReader
  attr_accessor :sql,
                :batch_size,
                :max_records

  def initialize(sql, batch_size, max_records = 100000)
    self.sql = sql
    self.batch_size = batch_size
    self.max_records = max_records
  end

  # takes a block that is yielded with each record fetched
  def read
    offset = 0

    # Fetch the next batch of records from the db.
    # Have an additional safeguard to not run into an infinite loop.
    # One might consider altering the safeguard to max db reads to be even safer
    while !(results = ActiveRecord::Base.connection.exec_query(query(offset))).empty? &&
          offset < max_records do

      records = results.to_hash

      offset += records.length

      # Iterate through the records.
      # Does not have to use #to_hash, could also be e.g. #rows
      results.to_hash.each do |record|
        yield record
      end
    end
  end

  # granted, this is dirty. There are probably better ways.
  def query(offset)
    sql + " LIMIT #{batch_size} OFFSET #{offset}"
  end
end
也许去看看。。。
reader = SqlDataReader.new("SELECT ...", 100)

reader.read do |record|
  # do something
end