【问题标题】:Data set too large to load into memory for processing数据集太大而无法加载到内存中进行处理
【发布时间】:2012-04-09 21:10:04
【问题描述】:

我有一个更大的快速增长的数据集,大约 400 万行,为了定义和排除异常值(用于统计/分析用途),我需要算法来考虑该数据集中的所有条目。然而,这是太多的数据加载到内存和我的系统阻塞。我目前正在使用它来收集和处理数据:

@scoreInnerFences = innerFence Post.where( :source => 1 ).
                                    order( :score ).
                                    pluck( :score )

使用典型的分治法是行不通的,我不认为因为必须考虑每个条目以保持我的异常值计算准确。如何有效地实现这一目标?

innerFence 识别数据集的下四分位数和上四分位数,然后使用这些发现来计算异常值。这是(尚未重构,非 DRY)代码:

def q1(s)
  q = s.length / 4

  if s.length % 2 == 0
    return ( s[ q ] + s[ q - 1 ] ) / 2
  else
    return s[ q ]
  end
end

def q2(s)
  q = s.length / 4

  if s.length % 2 == 0
    return ( s[ q * 3 ] + s[ (q * 3) - 1 ] ) / 2
  else
    return s[ q * 3 ]
  end
end

def innerFence(s)
  q1 = q1(s)
  q2 = q2(s)

  iq = (q2 - q1) * 3

  if1 = q1 - iq
  if2 = q2 + iq

  return [if1, if2]
end

【问题讨论】:

  • innerFence 是做什么的?显而易见的答案是在数据库中而不是在 Ruby 中的 innerFence 中做任何你正在做的事情——但这是否可能取决于 innerFence 的实际实现。
  • 它正在识别我的数据集的下四分位数和上四分位数,然后计算异常值。我在上次编辑中添加了源代码。

标签: mysql ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.2


【解决方案1】:

这不是最好的方法,但它是一种简单的方法:

做几个查询。首先你数分数:

q = Post.where( :source => 1 ).count

然后你做你的计算 然后你获取分数

q1 = Post.where(:source => 1)。 reverse_order(:分数)。 选择(“平均(分数)作为分数”)。 偏移量(q).limit((q%2)+1)

q2 = Post.where(:source => 1)。 reverse_order(:分数)。 选择(“平均(分数)作为分数”)。 偏移量(q*3).limit((q%2)+1)

代码可能是错误的,但我相信你明白了。

【讨论】:

  • 这条路线效果更好,我能够通过根据计数选择带偏移量的四分位数而不是将所有数据加载到导轨中来使其工作。谢谢!
  • 很高兴它有帮助!如果有人在您执行此操作的同时插入数据,您可能希望将其包装在事务中。
【解决方案2】:

对于大型数据集,我有时会下拉到 ActiveRecord 下方。即使我想,它也是一个记忆猪,使用 pluck。当然它的便携性较差,但有时它是值得的。

scores = Post.connection.execute('从score > 1 order by score的帖子中选择分数').map(&:first)

不知道这是否足以帮助记录 400 万条记录。如果没有,也许看看存储过程?

【讨论】:

  • 有时跳过 AR 是正确的,但在你的情况下,就像许多其他情况一样,它只会帮助你更快地击中自己的脚。 ;) 这个问题的解决比将数百万个数字加载到 Rails 中要简单得多。
猜你喜欢
  • 2014-01-08
  • 2018-12-04
  • 2013-03-03
  • 1970-01-01
  • 2017-06-01
  • 2020-11-24
  • 2020-08-06
  • 2019-01-13
  • 2015-05-26
相关资源
最近更新 更多