2

我使用Tire作为Elasticsearch的 Ruby 包装器。我的问题是我需要将 100,000 个文档加载到内存中并对它们进行复杂的计算。当前程序如下所示:

  1. 装入所有文件
  2. Computation.new(all_documents)
  3. 迭代所有文档并调用computation.calc(document)

此策略不适用于 100,000 个文档,因为我将立即达到机器的内存限制。文档 (JSON) 被加载到 Tire 对象中,然后我将其转换为 Ruby 哈希。

我能做些什么来制作这个规模?我想到了以下内容,但我不确定 a) 是否最好实施 b) 最佳解决方案。

  1. 初始化计算对象c = Computation.new
  2. 装入m 个文档
  3. c.preprocess(documents)
  4. 重复步骤 2 和 3,直到所有文档都被预处理
  5. 装入m 个文档
  6. 迭代m个文档
  7. c.calc(document)
  8. 重复步骤 6 和 7,直到处理完所有文档

同样从 GC 的角度来看,我不确定这将如何解决。

4

1 回答 1

1

您的问题似乎是“如何在不耗尽内存的情况下将 100,000 个 ElasticSearch JSON 对象序列化为 Ruby 对象?”。一个更好的问题是:“如何尽可能轻松高效地对 100,000 个 ElasticSearch 文档进行计算?”。由于我们不知道您要运行哪种计算,因此我们必须保持答案的一般性。

  1. 采纳neil-slater的建议并尽可能多地使用 ElasticSearch 。例如,ES 有很多不错的统计计算,你可以在 DB/store 中进行。
  2. 对插入新文档进行预处理。例如,如果您知道您将要针对整个集合获取计数、平均值或其他一些计算,只需在将每个项目存储到 ES 之前计算其统计信息。如果您在 Rails 中使用 Tire,请将这些 calc 方法添加到 before_save 回调或其他内容中。
  3. 避免将 ES 文档一起反序列化为 Ruby 对象。将所有 100,000 个对象都转换为 Ruby 对象正在扼杀你的记忆。看看您是否可以通过将结果作为直接 JSON 获取并使用 ruby​​ JSON gem(或一些性能调整的替代方案,如 multi-json)将它们转换为 ruby​​ 哈希来提高性能。它仍然会保留一些内存,但不会像完整的 Rails 模型对象那么多。
  4. 尝试将计算分解为多个步骤,并将它们作为后台作业或守护进程的任务提供。如果它们需要按顺序执行,您可以让第一个作业在下一个作业完成时触发它。
  5. 如果上述方法都不起作用,请找到一种更接近数据的方法(直接使用一些 javascript lib 操作 JSON)或考虑使用另一个数据存储,可能像 PostgreSQL 这样您可以在 DB 中以比您快 1000 倍的速度进行大量计算曾经可以在 Ruby/Rails 中使用。

希望有帮助!

于 2013-09-04T20:16:28.183 回答