Ruby on rails 在Ruby中使用哈希遍历表运行缓慢
我有下面的代码Ruby on rails 在Ruby中使用哈希遍历表运行缓慢,ruby-on-rails,ruby,hash,Ruby On Rails,Ruby,Hash,我有下面的代码 h2.each {|k, v| @count += 1 puts @count sq.each do |word| if Wordsdoc.find_by_docid(k).tf.include?(word) sum += Wordsdoc.find_by_docid(k).tf[word] * @s[word] end end rec_hash[k] = sum sum = 0 } h2-
h2.each {|k, v|
@count += 1
puts @count
sq.each do |word|
if Wordsdoc.find_by_docid(k).tf.include?(word)
sum += Wordsdoc.find_by_docid(k).tf[word] * @s[word]
end
end
rec_hash[k] = sum
sum = 0
}
h2->是一个包含文档ID的散列,该散列包含1000多个文档ID
Wordsdoc->是我数据库中的模型/表。。。
sq->是一个包含大约10个单词的散列
我正在做的是检查每个文档ID,然后对于sq中的每个单词,我在Wordsdoc表中查找该单词是否存在(Wordsdoc.find_by_docid(k).tf.include?(word),这里tf是{word=>value}的散列
如果是的话,我会在Wordsdoc中得到这个词的值,并将它与@s中的词的值相乘,这个值也是{word=>value}的散列
这似乎运行得很慢。Tt每秒处理一个文档。有没有办法处理得更快
非常感谢您在这方面的帮助!因为您有很多事情要做,我将为您提供更多的东西供您查看
inject
是一种方法,它可能会加快对sum
部分的操作去获取它们。你做了很多重复查询。虽然ActiveRecord可以在后台做一些缓存来加快速度,但它所能做的是有限的,没有理由让事情变得更困难 最明显的减速原因是
Wordsdoc.find\u by\u docid(k)
。对于k
的每个值,您调用它10次,每次调用它都有可能再次调用它。这意味着,对于h2
中的每个条目,您使用相同的参数调用该方法10-20次。对数据库的查询非常昂贵,因为数据库位于硬盘上,访问硬盘的费用也很高在任何系统中都是无效的。你可以很容易地调用Wordsdoc。在进入sq.each
循环之前,按Docid(k)
查找一次,并将其存储在一个变量中-这将节省大量查询并使循环运行得更快
另一个优化——虽然没有第一个优化那么重要——是在一个查询中获取所有Wordsdoc记录。几乎所有的优化都是中高级的(还有一些低级的!)编程语言和库在批量工作时工作得更好更快,ActiveRecord也不例外。如果您可以查询Wordsdoc
的所有条目,并通过h2
中的docid
键对其进行过滤,则可以进行1000次查询(在第一次优化之后。在第一次优化之前,它是10000-20000个查询)到一个单一的、巨大的查询。这将使ActiveRerocd和底层数据库能够以更大的块检索您的数据,并为您节省大量的磁盘访问
您还可以做一些较小的优化,但我指定的两个应该足够了。您正在调用
Wordsdoc。按docid(k)查找两次
您可以将代码重构为:
wordsdoc = Wordsdoc.find_by_docid(k)
if wordsdoc.tf.include?(word)
sum += wordsdoc.tf[word] * @s[word]
end
…但这仍然是丑陋和低效的
您应该批量预取所有记录,请参阅:
例如,类似的方法应该更有效:
Wordsdoc.find_in_batches(:conditions => {:docid => array_of_doc_ids}).each do |wordsdoc|
if wordsdoc.tf.include?(word)
sum += wordsdoc.tf[word] * @s[word]
end
end
此外,您还可以使用find_in_batches
方法中的:select=>:tf
从Wordsdoc表中仅检索某些列