CSV解析占用太多内存

市场

我正在尝试读取5MM的行文件,现在它超出了我在Heroku上占用的大量内存。我的方法有点快,大约每秒200次插入。.我相信它在导入时崩溃了。所以我的计划是分批导入1,000或10,000。我的问题是我怎么知道我在文件的末尾,ruby有一个.eof方法但有一个File方法,而且我不确定如何在循环中调用它

    def self.import_parts_db(file)
        time = Benchmark.measure do
            Part.transaction do 
                parts_db = []
                CSV.parse(File.read(file), headers: true) do |row|
                    row_hash = row.to_hash
                    part = Part.new(
                        part_num: row_hash["part_num"], 
                        description: row_hash["description"], 
                        manufacturer: row_hash["manufacturer"],
                        model: row_hash["model"],
                        cage_code: row_hash["cage_code"],
                        nsn: row_hash["nsn"]
                        )
                    parts_db << part
                end
                Part.import parts_db
            end
        end
        puts time
    end
埃里克·杜米尼尔(Eric Duminil)

第一个问题

一旦使用File.read(file)了巨大的文件,脚本将占用大量内存(可能过多)。您将整个文件读为1个巨大的字符串,即使CSV逐行读取它也是如此

当您使用具有数千行的文件时,它可能会正常工作。不过,您应该使用CSV.foreach改变

 CSV.parse(File.read(file), headers: true) do |row|

CSV.foreach(file, headers: true) do |row|

示例中,内存使用量从1GB变为0.5MB。

第二个问题

parts_db变成一个巨大的零件阵列,并一直保持增长,直到CSV文件的末尾。您需要删除交易记录(导入速度会很慢,但所需存储空间不会超过1行)或批量处理CSV。

这是一种可能的方法。我们CSV.parse再次使用,但仅用于2000行批处理:

def self.import_parts_db(filename)
  time = Benchmark.measure do
    File.open(filename) do |file|
      headers = file.first
      file.lazy.each_slice(2000) do |lines|
        Part.transaction do
          rows = CSV.parse(lines.join, write_headers: true, headers: headers)
          parts_db = rows.map do |_row|
            Part.new(
              part_num: row_hash['part_num'],
              description: row_hash['description'],
              manufacturer: row_hash['manufacturer'],
              model: row_hash['model'],
              cage_code: row_hash['cage_code'],
              nsn: row_hash['nsn']
            )
          end
          Part.import parts_db
        end
      end
    end
    puts time
  end
end

第三个问题?

先前的答案不应使用过多的内存,但是导入所有内容仍会花费很长时间,对于远程服务器来说可能太多。

使用枚举器的优点是可以轻松跳过批处理,并仅获取所需的批处理。

假设您的导入时间过长,并且在成功完成424000次导入后由于某种原因停止了导入。

您可以替换:

file.lazy.each_slice(2000) do |lines|

经过

file.lazy.drop(424_000).take(300_000).each_slice(2000) do |lines|

跳过前424000条CSV行,然后解析下300000条CSV行。

对于下一次导入,请使用:

file.lazy.drop(424_000+300_000).take(300_000).each_slice(2000) do |lines|

然后 :

file.lazy.drop(424_000+2*300_000).take(300_000).each_slice(2000) do |lines|

...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

HashMap如何占用内存?

来自分类Dev

SQLite查询占用太多CPU

来自分类Dev

更新UIImageView占用太多内存

来自分类Dev

printf()占用的内存

来自分类Dev

Solr筛选器缓存(FastLRUCache)占用太多内存并导致内存不足?

来自分类Dev

解析/读取具有最小内存占用的大型XML文件

来自分类Dev

我的iPhone应用程序占用了太多内存

来自分类Dev

xxhdpi图形占用太多空间

来自分类Dev

JDOM使用太多内存

来自分类Dev

Java套接字占用太多的CPU和虚拟内存

来自分类Dev

遍历学说集会占用太多内存

来自分类Dev

我的PHP zip函数占用了太多内存

来自分类Dev

ObjectInputStream消耗太多内存

来自分类Dev

BigInteger占用大量内存

来自分类Dev

内存占用增加

来自分类Dev

Python占用太多内存

来自分类Dev

使用“ this”指针的内存占用

来自分类Dev

从文档加载本体花费太多时间,并占用了我所有的内存空间

来自分类Dev

太多的内存被使用

来自分类Dev

我的iPhone应用程序占用了太多内存

来自分类Dev

Python CSV解析会填满内存

来自分类Dev

Flyweight模式-内存占用

来自分类Dev

结构数组占用太多内存

来自分类Dev

内存占用增加

来自分类Dev

为什么我的Android应用占用太多内存?

来自分类Dev

约会对话占用太多内存

来自分类Dev

从 18.10 升级到 19.04 后,`tracker-extract` 占用了太多内存,它冻结了我的机器

来自分类Dev

Jenkins 似乎在 CentOS 中占用了太多内存

来自分类Dev

await 对象占用的内存