性能优化在文件系统中搜索数据

时间:2018-11-18 23:46:45

标签: java file search optimization

我有一个与网络相关的存储,其中大约有500万个txt文件与大约300万笔交易相关。总数据大小约为3.5 TB。我必须在该位置搜索以查找与交易相关的文件是否可用,并且必须将两个单独的报告作为CSV文件“可用文件”和“不可用文件”进行报告。我们是  仍在JAVA 6中。由于必须递归搜索该位置,因此面临的挑战是,由于尺寸巨大,我平均需要2分钟左右的时间在该位置进行搜索。我正在使用Java I / O API进行递归搜索,如下所示。有什么办法可以改善性能?

File searchFile(File location, String fileName) {
     if (location.isDirectory()) {
         File[] arr = location.listFiles();
         for (File f : arr) {
             File found = searchFile(f, fileName);
             if (found != null)
                 return found;
         }
     } else {
         if (location.getName().equals(fileName)) {
             return location;
         }
     }
     return null;
}

4 个答案:

答案 0 :(得分:3)

您应该采用不同的方法,而不是每次搜索文件时都遍历整个目录,而应创建一个索引,该索引是从文件名到文件位置的映射。

本质上:

void buildIndex(Map index, File baseDir) {
    if (location.isDirectory()) {
        File[] arr = location.listFiles();
        for (File f : arr) {
            buildIndex(index, f);
        }
    } else {
        index.put(f.getName(), f);
    }
}

现在有了索引,搜索文件变得很简单。

现在您已经在地图中找到了文件,甚至还可以使用Set操作来找到交点:

Map index = new HashMap();
buildIndex(index, ...);
Set fileSet = index.keySet();
Set transactionSet = ...;
Set intersection = new HashSet(fileSet);
fileSet.retainAll(transactionSet);

或者,如果索引本身太大而无法保存在内存中,则可能要在SQLite数据库中创建索引。

答案 1 :(得分:1)

  • 在目录或网络关联存储中进行搜索是一种 噩梦:目录太大/太深时会花费很多时间。就像您在Java 6中一样, 因此,您可以遵循旧的时尚方法。列出CSV文件中的所有文件,例如 下面。
  • 例如
      

    查找。 -类型f -name'* .txt'>> test.csv。 (如果是Unix)

         

    dir / b / s * .txt> test.csv(如果是Windows)

  • 现在将此CSV文件加载到地图中,以将索引作为文件名。加载文件会花费一些时间,因为它会很大,但是一旦加载,然后在地图中搜索(因为它将是文件名)会更快,并且会大大减少搜索时间。

答案 2 :(得分:0)

您可以使用Java 6中提供的NIO FileVisitor

Path findTransactionFile(Path root) {
    Path transactionFile = null;
    Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            if (/* todo dir predicate*/ false) {
                return FileVisitResult.SKIP_SUBTREE; // optimization
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            if (/* todo file predicate*/ true) {
                transactionFile = file;
                return FileVisitResult.TERMINATE; // found    
            }
            return FileVisitResult.CONTINUE;
        }
    });

    return transactionFile;
}

答案 3 :(得分:0)

我不知道答案,但是从算法的角度来看,您的程序具有最差的复杂性。每单查询一次交易,就会迭代所有文件(500万个)。您有300万笔交易。

我的建议是迭代文件(500万个文件)并基于文件名建立索引。然后迭代事务并搜索索引,而不是完全扫描。 或者可能有第三方免费工具可以索引大型文件系统,然后可以由外部应用程序(在这种情况下为Java应用程序)访问该索引。如果找不到这种工具,最好进行发明(然后可以以适合您需求的最佳方式建立索引)。