Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 验证网络上是否存在3.5亿个文件_C#_.net_Sql Server_Tsql - Fatal编程技术网

C# 验证网络上是否存在3.5亿个文件

C# 验证网络上是否存在3.5亿个文件,c#,.net,sql-server,tsql,C#,.net,Sql Server,Tsql,我有一个SQL Server表,其中包含大约300000000个绝对UNC路径,我正在尝试(快速)验证每个路径,以确保SQL Server表中的路径实际上作为磁盘上的文件存在 从表面上看,我正在以50000个批次查询表,并增加一个计数器,以便在前进时推进批次 然后,我使用一个数据读取器对象来存储我当前的批集,并在批中循环,使用file.Exists(path)命令检查每个文件,如下面的示例所示 问题是,我在一个具有16gb ram的四核3.4ghz i5上每秒最多处理1000个文件,这将需要几天

我有一个SQL Server表,其中包含大约300000000个绝对UNC路径,我正在尝试(快速)验证每个路径,以确保SQL Server表中的路径实际上作为磁盘上的文件存在

从表面上看,我正在以50000个批次查询表,并增加一个计数器,以便在前进时推进批次

然后,我使用一个数据读取器对象来存储我当前的批集,并在批中循环,使用
file.Exists(path)
命令检查每个文件,如下面的示例所示

问题是,我在一个具有16gb ram的四核3.4ghz i5上每秒最多处理1000个文件,这将需要几天的时间。有没有更快的方法


我在SQL Server表上有一个列存储索引,并且我已经对它进行了分析。我在中获得了成批的50k条记录,瓶颈很可能是网络流量,或者更具体地说是:SMB流量。您的计算机与SMB对话以从网络存储中检索文件信息。SMB流量是“闲聊”的,您需要一些消息来检查文件的存在性和您读取文件的权限

值得一提的是,在我的网络上,我可以通过SMB每秒查询大约100个文件,而递归列出15K个文件需要10秒

更快的方法是提前检索上的远程目录列表。如果目录结构是可预测的-如果存储在这些目录中不包含许多不相关的文件,这将是微不足道的

那么您的代码将如下所示:

HashSet<string> filesOnNetwork = new HashSet<string>(Directory.EnumerateFiles(
                            baseDirectory, "*.*", SearchOption.AllDirectories));

foreach (var fileToCheck in filesFromDatabase)
{
    fileToCheckExists = filesOnNetwork.Contains(fileToCheck);
}
HashSet filesOnNetwork=新的HashSet(Directory.EnumerateFiles)(
baseDirectory,“**”,SearchOption.AllDirectories));
foreach(var fileToCheck-in filesFromDatabase)
{
fileToCheckExists=filesOnNetwork.Contains(fileToCheck);
}

如果网络上的文件比您需要检查的文件多得多,这可能会产生负面影响,因为填充和搜索
文件连接网络将成为您应用程序的瓶颈。

优化SQL端在这里没有意义,因为您是文件IO绑定的

我将使用
Directory.EnumerateFiles
获取所有存在文件的列表。枚举目录中的文件应该比单独测试每个文件快得多

您甚至可以将问题完全颠倒过来,并将该文件列表大容量插入数据库临时表中,以便在数据库中正确执行基于SQL的集合处理

如果您想单独进行测试,您可能应该并行进行。目前还不清楚这个过程是否真的是磁盘绑定的。可能是网络或CPU受限

通过重叠多个请求,并行性将在这方面有所帮助。问题可能在于网络延迟,而不是带宽。在DOP 1时,在任何给定时间至少有一台机器处于空闲状态。有时两者都是空闲的


与我想要检查的文件相比,那里实际托管的文件数量是3到4倍

使用
dir/b
命令将所有文件名的列表导入.txt文件。在有文件的机器上本地执行,但如果不可能,则远程执行。然后使用
bcp
将它们批量插入到数据库的表中。然后,您可以在单个SQL查询中执行快速存在性检查,这将得到高度优化。你将得到一个散列连接


如果您想并行执行此策略的
dir
阶段,您可以为此编写一个程序。但是也许没有必要这样做,尽管是单线程的,dir还是足够快。

在您当前的解决方案中,获得50000个批并打开和关闭连接除了减缓速度之外没有任何作用。数据读取器流。只需打开一次,然后一次一个地阅读。在封面下,阅读器将一次发送批。当您只读取了10行数据时,DataReader不会试图用300000000行阻塞客户端

我认为您担心优化从SQL读取的最快步骤

验证文件路径将是最慢的步骤

我喜欢CodeCaster给出的答案,但在3.5亿美元的情况下,你将进入.NET的对象大小限制。通过读取哈希集,直到完成该步骤,它才开始工作

我会使用一个带有两个集合的

  • 枚举文件
  • 写入数据库
最慢的步骤是读取文件名,所以尽可能快地读取,不要中断。在靠近存储设备的设备上执行此操作。在连接SAN的设备上运行该程序

我知道你们会说写db很慢,但它只需要比枚举文件快。只需为found设置一个二进制列-不要将完整文件名写入#temp。我打赌美元到甜甜圈(优化)更新比枚举文件快。一次分块更新10000行,以减少往返次数。我会异步进行更新,这样您就可以在处理当前更新时构建下一个更新

最后,您必须检查数据库中是否有任何未标记为已找到的文件

不要先去中间收藏。直接处理枚举。这可以让您立即开始工作,并降低内存

foreach (string  fileName in Directory.EnumerateFiles(baseDirectory, "*.*", SearchOption.AllDirectories)) 
{
   // write filename to blocking collection
}

如果CodeCaster的方法由于远程服务器上的文件太多而无法工作,并且如果您能够在远程服务器上安装新程序,那么有一个快速的想法:编写一个安装在每台服务器上的程序,并侦听HTTP请求的某个端口(或您喜欢的任何web服务技术)。查询数据库的程序应该对每台服务器的文件名进行批处理,并向每台服务器发送一个包含该服务器上所有文件名的请求。web服务检查文件是否存在(这应该很快,因为它现在是一个本地操作),并响应,例如,仅包含实际存在的文件名的列表
foreach (string  fileName in Directory.EnumerateFiles(baseDirectory, "*.*", SearchOption.AllDirectories)) 
{
   // write filename to blocking collection
}