File.Move以外的文件移动方法更快

我有一个控制台应用程序,大约需要625天才能完成。 除非有办法让它更快。

首先,我正在一个目录中工作,如果不是更多的话,它有大约4,000,000个文件。 我正在一个数据库中工作,每个文件都有一行,然后是一些。

现在使用SQL相对较快,瓶颈就是当我使用File.Move()每次移动需要18秒才能完成。

有比File.Move()更快的方法吗?

这是瓶颈:

 File.Move(Path.Combine(location, fileName), Path.Combine(rootDir, fileYear, fileMonth, fileName)); 

所有其他代码都运行得非常快。 我需要做的就是将一个文件移动到一个新位置,然后更新数据库位置字段。

如果需要,我可以显示其他代码,但实际上上面是唯一的当前瓶颈。

事实certificate,从File.Move切换到设置FileInfo并使用.MoveTo显着提高了速度。

它现在将在大约35天内运行,而不是625天。

 FileInfo fileinfo = new FileInfo(Path.Combine(location, fileName)); fileinfo.MoveTo(Path.Combine(rootDir, fileYear, fileMonth, fileName)); 

18秒并不是很不寻常。 当单个目录中有大量文件时,NTFS的性能不佳。 当你要求一个文件时,它必须对其目录数据结构进行线性搜索。 有1,000个文件,这不会花太长时间。 有10,000个文件你会注意到它。 有400万个文件。 。 。 是的,需要一段时间。

如果将所有目录条目预加载到内存中,则可以更快地执行此操作。 然后,不要为每个文件调用FileInfo构造函数,而只需在字典中查找它。

就像是:

 var dirInfo = new DirectoryInfo(path); // get list of all files var files = dirInfo.GetFileSystemInfos(); var cache = new Dictionary(); foreach (var f in files) { cache.Add(f.FullName, f); } 

现在,当您从数据库中获取名称时,您可以在字典中查找它。 这可能比每次尝试从磁盘上获取它更快。

您可以并行移动文件,也可以使用Directory.EnumerateFiles为您提供一个延迟加载的文件列表(当然我还没有用4,000,000个文件测试它):

 var numberOfConcurrentMoves = 2; var moves = new List(); var sourceDirectory = "source-directory"; var destinationDirectory = "destination-directory"; foreach (var filePath in Directory.EnumerateFiles(sourceDirectory)) { var move = new Task(() => { File.Move(filePath, Path.Combine(destinationDirectory, Path.GetFileName(filePath))); //UPDATE DB }, TaskCreationOptions.PreferFairness); move.Start(); moves.Add(move); if (moves.Count >= numberOfConcurrentMoves) { Task.WaitAll(moves.ToArray()); moves.Clear(); } } Task.WaitAll(moves.ToArray());