1

我有以下代码

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 个这些 Wordsdoc -> 是我数据库中的模型/表... sq -> 是一个包含大约 10 个单词的哈希

我正在做的是遍历每个文档 ID,然后对于 sq 中的每个单词,如果该单词存在,我会在 Wordsdoc 表中查找(Wordsdoc.find_by_docid(k).tf.include?(word) ,这里 tf 是 {word => value} 的哈希

如果是这样,我会在 Wordsdoc 中获取该单词的值,并将其与 @s 中的单词的值相乘,这也是 {word = > value} 的哈希

这似乎运行得很慢。Tt 每秒处理一个文档。有没有办法更快地处理这个?

非常感谢您对此的帮助!

4

3 回答 3

2

你做了很多重复的查询。虽然 ActiveRecord 可以在后台进行一些缓存以加快速度,但它可以做的事情是有限的,没有理由让它变得更难。

放缓的最明显原因是Wordsdoc.find_by_docid(k). 对于 的每个值k,您调用它 10 次,每次调用它都有可能再次调用它。这意味着您使用相同的参数为h2. 对数据库的查询是昂贵的,因为数据库在硬盘上,并且在任何系统中访问硬盘都是昂贵的。您可以在进入循环之前轻松调用Wordsdoc.find_by_Docid(k) 一次sq.each,并将其存储在一个变量中 - 这将节省大量查询并使您的循环运行得更快。

另一项优化——虽然不如第一个重要——是在单个查询中获取所有 Wordsdoc 记录。几乎所有中高级(还有一些低级!)编程语言和库在批量工作时工作得更好更快,ActiveRecord 也不例外。如果您可以查询 的所有条目Wordsdoc,并通过docid's inh2的键对其进行过滤,则可以将 1000 个查询(在第一次优化之后。在第一次优化之前是 10000-20000 个查询)变成一个巨大的查询。这将使 ActiveRerocd 和底层数据库能够以更大的块检索您的数据,并为您节省大量磁盘访问。

您可以做一些更小的优化,但我指定的两个应该绰绰有余。

于 2012-04-25T10:51:32.373 回答
1

你打Wordsdoc.find_by_docid(k)了两次电话。

您可以将代码重构为:

wordsdoc = Wordsdoc.find_by_docid(k)
if wordsdoc.tf.include?(word)
  sum += wordsdoc.tf[word] * @s[word]
end

...但它仍然是丑陋和低效的。

您应该分批预取所有记录,请参阅:https ://makandracards.com/makandra/1181-use-find_in_batches-to-process-many-records-without-tearing-down-the-server

例如,这样的事情应该更有效:

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

您也可以使用例如:select => :tfinfind_in_batches方法仅从 Wordsdoc 表中检索某些列。

于 2012-04-25T11:19:19.800 回答
0

由于您有很多事情要做,我只想为您提供要检查的东西。

  1. 一本名为Eloquent Ruby的书处理文档并遍历文档以计算单词被使用的次数。他的所有示例都是关于他正在维护的文档系统,因此它甚至可以为您解决其他问题。
  2. inject可能是一种可以加快您为sum零件做的事情的方法。
  3. 如果您异步执行此操作,则延迟整个工作。这意味着如果这是一个网络应用程序,如果您等待 1000 秒以完成此作业,然后它会在屏幕上显示它的答案,那么您必须超时。

去拿他们。

于 2012-04-25T10:49:34.923 回答