评估Ruby和Mongo的性能:文件中有160万条小记录,向Mongo写入800K条记录需要15分钟?更有效的方法?
我们在一个平面文件中有160万条记录。每条记录包含三个或四个少于100个字符的短字符串 我们只需要800K的这些记录。我们将这些记录写入Mongo收藏。其他800K被忽略 处理文件大约需要15分钟,这意味着我们每秒处理约1.67K条记录。这是预期的性能,还是过程应该快得多(例如,5K记录/秒、10K记录/秒) 下面的代码(@skip是大约800K个应用程序ID的散列)评估Ruby和Mongo的性能:文件中有160万条小记录,向Mongo写入800K条记录需要15分钟?更有效的方法?,ruby,mongodb,Ruby,Mongodb,我们在一个平面文件中有160万条记录。每条记录包含三个或四个少于100个字符的短字符串 我们只需要800K的这些记录。我们将这些记录写入Mongo收藏。其他800K被忽略 处理文件大约需要15分钟,这意味着我们每秒处理约1.67K条记录。这是预期的性能,还是过程应该快得多(例如,5K记录/秒、10K记录/秒) 下面的代码(@skip是大约800K个应用程序ID的散列) def updateApplicationDeviceTypes(目录,限制) 将“更新应用程序数据(传递3-设备类型) fil
def updateApplicationDeviceTypes(目录,限制)
将“更新应用程序数据(传递3-设备类型)
file=file.join(dir,“/application\u device\u type”)
cols=getColumns(文件)
设备类型id列=列[:设备类型id]
更新=Proc.new do | id,组|
@应用程序\u coll.update(
{“itunes_id”=>id},
{:$set=>{“设备”=>group}
#如果一个id的所有记录都不是相邻的,那么您将需要这个
#{:$addToSet=>{“设备”=>{:$each=>group}}
)除非!id或@skip[id.intern]
结束
getValue=Proc.new{| r | r[设备类型_id_col]}
batchRecords(文件、cols[:应用程序\u id]、更新、获取值、限制)
结束
#在对数组/id调用“更新”之前,将结果添加到数组
def批处理记录(文件名、idCol、更新、getValue、限制=nil)
当前id=零
当前_组=[]
每个记录(文件名、限制)都要|
id=r[idCol]
value=getValue.call(r)
if id==当前_id和!价值,零?
当前的模式设计和应用程序的读写模式对应用程序的性能起着极其重要的作用
我建议在查看机器和IO级性能之前启用探查器:
您还可能会发现去年的MongoSV中的这些演讲很有用:
您的性能取决于:Cpu的数量和速度、缓存的大小、内存的大小、IO子系统/磁盘的速度。是什么让你认为我们只知道一个参数(编程语言)就可以判断你的性能对不起,@Klaus。假设在标准Macbook Pro上进行开发。具体规格:处理器:2.26 Ghz Intel Core 2 Duo内存:4GB 1067 Mhz DDR3硬盘:500 GB,5400 RPM最重要的信息-您如何将它们写入此集合?有索引吗?磁盘速度相当慢-我敢打赌,您的限制因素将是IO带宽(写入必须与磁盘同步,并且您的磁盘只支持这么多IOPs)。您可以使用mongo发行版中提供的“mongoperf”工具测试机器上IOPS的精确限制。是的,有索引。我们正在更新,而不是插入。据我们所知,mongo没有批量更新。谢谢,Brandon。我们用我们的方法更新了这个问题。它非常简单,从文件(不是DB)读取数据,然后写入Mongo。
def updateApplicationDeviceTypes(dir, limit)
puts "Updating Application Data (Pass 3 - Device Types)..."
file = File.join(dir, '/application_device_type')
cols = getColumns(file)
device_type_id_col = cols[:device_type_id]
update = Proc.new do |id, group|
@applications_coll.update(
{ "itunes_id" => id },
{ :$set => { "devices" => group } }
# If all records for one id aren't adjacent, you'll need this instead
#{ :$addToSet => { "devices" => { :$each => group } } }
) unless !id or @skip[id.intern]
end
getValue = Proc.new { |r| r[device_type_id_col] }
batchRecords(file, cols[:application_id], update, getValue, limit)
end
# result to an array, before calling "update" on the array/id
def batchRecords(filename, idCol, update, getValue, limit=nil)
current_id = nil
current_group = []
eachRecord(filename, limit) do |r|
id = r[idCol]
value = getValue.call(r)
if id == current_id and !value.nil?
current_group << value
else
update.call(current_id, current_group) unless current_id.nil?
current_id = id
current_group = value.nil? ? [] : [value]
end
end
# Since the above is only called once for each row, we still
# have one group to update.
update.call(current_id, current_group)
end