我们现在有一千万条左右的数据,需要针对其中的每一条进行操作 大体的逻辑是这样,很简单
lot_of_rows.each do |row|
# Resque.enqueue(job, row)
end
一开始数据量很小,不用 resque, 一个 each 就行了。后来数据量大了,上了 resque, 也从原来的一个 each 分成了很多小的 each,逻辑大体变成这样(当然,日期是计算的,不是写死的:) ):
XX.where(created_at: Time.local(2012, 1)..Time.local(2012,2).each do ||
end
XX.where(created_at: Time.local(2012, 2)..Time.local(2012,3).each do ||
end
像这种情况各位有没有什么更好的方法呢。处理大数据一点经验也没啊
单从这几行代码看,把 each 换成 find_each,不过像你说的那个数据量的话 find_each 后对数据做处理后最终还是要自己构造 sql 语句批量 insert 和 update
ruby 当然适合,只要有 thread/process 的语言都适合 并行处理就对了,注意下数据库链接是不是 thread safe 的 比如用这个 http://burgestrand.se/code/ruby-thread-pool/
1000 万不用什么特殊的,如之前所说,用 java/jruby 写,开几个线程跑就好了。 数据最好 dump 到文件,避免对数据库造成压力,处理起来也简单。
#8 楼 @Rei #9 楼 @ltl3884 MongDB 自身的 MapReduce 是单线程的(原因:它是由 Mongo Shell 支持的,而后者是 JavaScript)。所以如果你要作的操作本身仅对一条数据进行改动(这里单纯理解 MapReduce 要对所有数据进行汇总),那恐怕用 MapReduce 帮助不大,而且内存使用和性能影响也不小。
另外,考虑到 Ruby Driver 的语法跟 shell js 语法差不多,如果是 Mongoid 或 driver 上开销大,可以尝试一下直接在 mongo shell 里进行操作。
PS,如果是要用 MapReduce 来做统计,那么将数据 dump 到另一个不直接使用的 mongod 上,或是一个 secondary node 上来进行会更好一点。
之前优化了一个跑数据的任务,数据在 150W * 8,从 40 天 -10 天 -1 天,用的就是 ruby,那次瓶颈在网络 IO,因为要通过 http 得到图片,去计算图片的分辨率,因为历史原因,图片分布在多台机器上,后来还是改成了 socket,然后跑数据的还是在一台机子上 fork 了多个进程一起跑。主要还是找出根本原因吧。
先谢谢各位了。我的这个情况逻辑很简单,用 mapreduce 的话好你都找不到要 reduce 啥,内存这个问题到是确实有,一次返回的结果大一些内存就飚上去了。数据分段有什么好的建议吗?因为即使是 mapreduce 也不会一次把数据都取回来吧,我现在就是一个月的一组,以后可能要每周一组了,或者有类似的实现不
建议先做数据库优化,索引很重要,可以考虑分表,读写分离。实时性不是很高的需求不建议用队列,这种一个操作就要更改上 1000 万条数据的需求真的并不多,客户又不要求你一下把这上 1000 万的数据给列出来。