2

我需要将文件从一个目录复制到另一个目录,具体取决于 SQL 数据库表中文件名的存在。

为此,我使用以下代码:

using(SqlConnection connection = new SqlConnection("datasource or route"))
{

  connection.Open();

  using(SqlCommand cmd = new SqlCommand("SELECT idPic, namePicFile FROM DocPicFiles", connection))
  using (SqlDataReader reader = cmd.ExecuteReader())
  {

    if (reader != null)
    {
      while (reader.Read())
      {
        //picList IS AN ARRAY THAT Contains All the files names in a directory
        if (picList.Any(s => s.Contains(reader["namePicFile"].ToString())))
        {
          File.Copy("theFile  in the Directory or array picList",  "the destiny directory"+ ".jpg", false)
        }
      }
    }
  }
}

有什么办法可以在更短的时间内完成吗?20.876 条记录需要 1 小时。

4

4 回答 4

10

File.Copy 尽可能快。您必须记住,您取决于硬件决定的文件传输速度,并且在 20000 个文件时,数据访问的延迟也会发挥作用。如果您在 HDD 上执行此操作,则在切换到 SSD 或其他一些快速介质后,您可能会看到很大的改进。

仅就这种情况而言,硬件很可能是您的瓶颈。

编辑:我认为长时间保持与数据库的连接是一种不好的做法。我建议您在一些内存缓存(数组、列表等)中获取所有需要的数据,然后在复制文件时对其进行迭代。数据库连接是一种宝贵的资源,对于必须处理高并发(但不仅如此)的应用程序,快速释放连接是必须的。

于 2015-08-26T21:23:20.563 回答
7

请允许我猜一下 - 嗯……不。没有办法更快地做到这一点。

我怎么这么自信?因为文件复制需要与磁盘通信,这是一个非常缓慢的操作。更进一步,如果您尝试使用多线程,结果将变得更慢而不是更快,因为将磁头移动到磁盘上的“机械”操作不再是顺序的,这可能是偶然的。

请参阅我之前提出的这个问题的答案

所以,是的,如果您还没有使用 SSD,请尝试使用 SSD,否则您已经获得了最好的。

下面我们来看看与缓存相比,磁盘写入速度慢意味着什么。如果缓存访问需要 10 分钟,则意味着从磁盘读取需要 2 年。所有访问都显示在下图中。显然,当您的代码将执行时,瓶颈将是磁盘写入。最好的办法是让磁盘写入保持顺序。

在此处输入图像描述

于 2015-08-26T21:23:31.663 回答
4

由于您的 i/o 子系统几乎肯定是这里的瓶颈,因此使用并行任务库可能与它得到的一样好:

static void Main(string[] args)
{
  DirectoryInfo source      = new DirectoryInfo( args[0] ) ;
  DirectoryInfo destination = new DirectoryInfo( args[1] ) ;

  HashSet<string> filesToBeCopied = new HashSet<string>( ReadFileNamesFromDatabase() , StringComparer.OrdinalIgnoreCase ) ;

  // you'll probably have to play with MaxDegreeOfParallellism so as to avoid swamping the i/o system
  ParallelOptions options= new ParallelOptions { MaxDegreeOfParallelism = 4 } ;

  Parallel.ForEach( filesToBeCopied.SelectMany( fn => source.EnumerateFiles( fn ) ) , options , fi => {
      string destinationPath = Path.Combine( destination.FullName , Path.ChangeExtension( fi.Name , ".jpg") ) ;
      fi.CopyTo( destinationPath , false ) ;
  }) ;

}

public static IEnumerable<string> ReadFileNamesFromDatabase()
{
  using ( SqlConnection connection = new SqlConnection( "connection-string" ) )
  using ( SqlCommand cmd = connection.CreateCommand() )
  {
    cmd.CommandType = CommandType.Text ;
    cmd.CommandText = @"
      select idPic ,
             namePicFile
      from DocPicFiles
      " ;

    connection.Open() ;
    using ( SqlDataReader reader = cmd.ExecuteReader() )
    {
      while ( reader.Read() )
      {
        yield return reader.GetString(1) ;
      }
    }
    connection.Close() ;

  }
}
于 2015-08-26T22:12:06.310 回答
0

我通过使用参数创建单个压缩文件 (.zip) 来解决此问题,以仅存储文件(无压缩)。创建单个 (.zip) 文件,移动该单个文件,然后在该位置展开,事实证明在处理数千个文件时要快 2 倍。

于 2018-03-19T17:30:20.683 回答