我有一个SQL Server表,大约有300,000,000个绝对UNC路径,我正在尝试(快速)验证每个路径,以确保SQL Server表中的路径实际上作为磁盘上的文件存在.
从表面上来看,我正在以50,000个批量查询表格,然后递增一个计数器来推进我的批次.
然后,我使用数据读取器对象来存储我当前的批处理集并循环遍历批处理,使用File.Exists(path)
命令检查每个文件,如下例所示.
问题是,我正在处理大约.四核心3.4ghz i5最大每秒1000个文件,16GB内存,这需要几天时间.有更快的方法吗?
我在SQL Server表上有一个列存储索引,我已对它进行了分析.我在<1s中获得了50k的批量记录,因此在向.net控制台应用程序发布批次时,这不是SQL瓶颈.
while (counter <= MaxRowNum) { command.CommandText = "SELECT id, dbname, location FROM table where ID BETWEEN " + counter + " AND " + (counter+50000).ToString(); connection.Open(); using (var reader = command.ExecuteReader()) { var indexOfColumn1 = reader.GetOrdinal("ID"); var indexOfColumn2 = reader.GetOrdinal("dbname"); var indexOfColumn3 = reader.GetOrdinal("location"); while (reader.Read()) { var ID = reader.GetValue(indexOfColumn1); var DBName = reader.GetValue(indexOfColumn2); var Location = reader.GetValue(indexOfColumn3); if (!File.Exists(@Location.ToString())) { //log entry to logging table } } } // increment counter to grab next batch counter += 50000; // report on progress, I realize this might be off and should be incremented based on ID Console.WriteLine("Last Record Processed: " + counter.ToString()); connection.Close(); } Console.WriteLine("Done"); Console.Read();
编辑:添加一些额外的信息:
想通过数据库本身做这一切; 它是sql服务器企业,拥有2tb内存和64个内核.问题是sql server服务帐户无法访问托管数据的nas路径,所以我的cmdshell通过SP运行失败(我不控制AD的东西),UNC路径有成千上万的个别子基于文件的MD5哈希的目录.所以枚举目录的内容最终没有用,因为你可能有一个文件10个目录深只有1个文件.这就是我必须进行文字全路径匹配/检查的原因.
哦,路径一般都很长.我实际上尝试将它们全部加载到内存中的列表,然后才意识到它相当于90gb的数据(lol,oops).完全同意其他评论.数据库速度超快,完全没有担心.虽然不考虑SMB聊天,但很可能就是我正在遇到的问题. - JRats 13小时前
哦! 如果文件不存在,我也只更新数据库.如果确实如此,我不在乎.因此,我的数据库运行最小化以获取批量路径.基本上,我们将一堆数据从较慢的存储迁移到这个灵活的设备,并且我被要求确保通过编写一些内容来验证每个文件是否存在.
线程帮助了很多.我跨越4个线程的文件检查并使我的处理能力达到约3,300条记录/秒,这要好得多,但我仍然希望能够更快地获得更快.有没有一个很好的方法来判断我是否受到SMB流量的约束?我注意到,一旦我试图将我的线程计数提高到4或5,我的速度就会下降到涓涓细流; 我想也许我在某处陷入僵局,但没有.
哦,我不能对你说的确切原因进行FilesOnNetwork检查,与我要检查的内容相比,实际托管的文件数量是3或4倍.灵活的设备可能有1.5b左右的文件.
优化SQL端在这里没有意义,因为您是文件IO绑定.
我会Directory.EnumerateFiles
用来获取存在的所有文件的列表.枚举目录中的文件应该比单独测试每个文件快得多.
您甚至可以完全反转问题,并将该文件列表批量插入数据库临时表,以便您可以在数据库中执行基于SQL的集处理.
如果您想继续单独测试,您可能应该并行执行此操作.目前尚不清楚该进程是否真的受磁盘限制.可能是网络或CPU绑定.
并行性将通过重叠多个请求来帮助实现.这是网络延迟,而不是可能成为问题的带宽.在DOP 1,至少一台机器在任何给定时间都处于空闲状态.有时候两者都是空闲的.
与我想要检查的文件相比,实际托管的文件数量是3到4倍
使用此dir /b
命令将所有文件名的列表传递到.txt文件中.在具有文件的计算机上本地执行,但如果不可能远程执行.然后使用bcp
它们将它们批量插入到数据库的表中.然后,您可以在单个SQL查询中执行快速存在检查,该查询将进行高度优化.你将获得一个哈希加入.
如果你想并行dir
化这个策略的阶段,你可以为此编写一个程序.但也许没有必要,尽管是单线程的,但dir足够快.
瓶颈最可能是网络流量,或者更具体地说:SMB流量.您的计算机会与SMB通信以从网络存储中检索文件信息.SMB流量"很蹩脚",您需要一些消息来检查文件的存在以及您是否有权阅读它.
对于它的价值,在我的网络上,我可以通过SMB查询每秒大约一百个文件的存在,而递归列出15K文件需要10秒.
什么能更快的检索远程目录事先列出的.如果目录结构是可预测的 - 并且存储在这些目录中不包含许多不相关的文件,那么这将是微不足道的.
然后你的代码将如下所示:
HashSetfilesOnNetwork = new HashSet (Directory.EnumerateFiles( baseDirectory, "*.*", SearchOption.AllDirectories)); foreach (var fileToCheck in filesFromDatabase) { fileToCheckExists = filesOnNetwork.Contains(fileToCheck); }
如果网络上的文件多于您需要检查的文件,则可能会产生不利影响,因为填写和搜索filesOnNetwork
将成为您的应用程序的瓶颈.