【问题标题】:Searching for matches in 3 million text files [closed]在 300 万个文本文件中搜索匹配项 [关闭]
【发布时间】:2013-11-25 20:38:12
【问题描述】:

我有一个简单的要求,用户输入一堆单词,系统扫描超过 300 万个文本文件并找到包含这些关键字的文件。如果没有复杂的搜索/索引算法,最有效和最简单的方法是什么?

我曾想过为此使用Scanner 类,但不知道在如此大的文件上的性能。性能不是很高的优先级,但应该在可接受的标准内。

【问题讨论】:

  • 您可能需要考虑将关键字存储在数据库中,并使用它来查找匹配项。
  • 我会认真考虑使用数据库来实现这种方法,数据库是针对性能进行优化的。还有你说有300万个文本文件,但后来你注意到performance over such large files,你的意思是这里有大量文件吗? Scanner 方法可能适用于正常大小的文件,但我想会影响性能。
  • 会有300万+个文件。每个人都有大约 14000 个自然语言单词
  • 为什么“没有复杂的搜索/索引算法”?定义复杂,具体说明为什么你有这个约束?当你在做的时候,什么是“可接受的标准”性能?客户在 3 或 4 个工作日内收到回复? :D

标签: java file-io


【解决方案1】:

应该是可以接受的标准

我们不知道可接受的标准是什么。如果我们谈论交互式用户,可能不会有一个简单的解决方案可以扫描 300 万个文件并在 5 秒内返回一些内容。

一个合理的解决方案是搜索索引,可能基于Lucence

基于扫描仪/grep/find 等的解决方案的主要问题是它们速度慢,无法扩展,并且必须一遍又一遍地完成昂贵的扫描工作(除非您存储中间结果...但这并不简单,而且基本上是重新实现索引器的人工成本高昂)。使用索引时,只有索引的创建和更新成本很高,查询成本很低。

【讨论】:

    【解决方案2】:

    如果没有复杂的搜索/索引算法,最有效和最简单的方法是什么?

    复杂的搜索/索引算法。没有必要在这里重新发明轮子。由于用户可以输入任何单词,因此您无法进行简单的预处理步骤,而是必须对文本中的所有单词进行索引。这就是 Lucene 为您所做的事情。

    除了预处理和建立索引之外,没有其他快速搜索文本的方法。您可以为此推出自己的解决方案,也可以只使用 Lucene。

    没有预处理的简单文本搜索将太慢而无法使用。

    【讨论】:

    • 谢谢大家。我决定使用 solr 进行索引。
    【解决方案3】:

    为什么不将系统调用包装到 grep?您可以通过 Runtime 类来实现。

    【讨论】:

    • Grep 可能在系统上不可用,如果您在 Windows 上部署就是这种情况。 Grep 也会比正确的索引慢。
    • 确实索引会更快。但是 grep 也可以在 Windows 上使用,如果性能不是高优先级,它将是一个更快的开发。而且您仍然可以并行化您的 grep 调用。
    • grep 只有在您特意安装它的情况下才能在 Windows 上使用。除非您实际上对目标系统负责,否则您不能指望它在您的目标系统上可用。
    【解决方案4】:

    在解析每个文本文件时,我会使用BufferedReader 并检查每一行文本是否匹配。

    BufferedReader br = new BufferedReader(new FileReader(file));
    String line;
    while ((line = br.readLine()) != null) {
       // Does this line containe the text?
       if(line.contains(text)) {
          System.out.println("Text found");
       }
    }
    br.close();
    

    我不确定这对于如此大量的文件是否会非常快。

    【讨论】:

    • 这会非常慢。
    【解决方案5】:

    What would be the most efficient and simple way to implement this without a complex searching / indexing algorithm

    如果您不使用任何类型的索引算法,那么每次提交搜索时,您都需要读取每个文件。这样做的开销不在于“匹配”算法,而在于 I/O 延迟。所以,我不会太在意使用什么来匹配; Scanner 是直接的选择。

    如果您想提高性能,则需要使用某种预处理。您可以在大小允许的情况下将文件加载到内存中。您可以为每个文件(索引)创建一组单词。有太多算法供您搜索,尤其是 Map/Reduce 上下文中的“字数统计”示例。如果您想获得更高的并发性,您可能还想看看 Java 的 Fork/Join 框架。

    【讨论】:

      猜你喜欢
      • 2018-09-07
      • 2019-04-10
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-18
      • 1970-01-01
      相关资源
      最近更新 更多