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
    部分的操作
  • 延迟作业如果您异步执行此操作,则整个操作都会延迟。这意味着如果这是一个web应用程序,则如果您等待1000秒以完成此作业,然后在屏幕上显示其答案,则必须超时

  • 去获取它们。

    你做了很多重复查询。虽然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表中仅检索某些列