当前位置:  开发笔记 > 编程语言 > 正文

通过网络验证3.5亿个文件的存在

如何解决《通过网络验证3.5亿个文件的存在》经验,为你挑选了2个好方法。

我有一个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左右的文件.



1> usr..:

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

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

您甚至可以完全反转问题,并将该文件列表批量插入数据库临时表,以便您可以在数据库中执行基于SQL的集处理.

如果您想继续单独测试,您可能应该并行执行此操作.目前尚不清楚该进程是否真的受磁盘限制.可能是网络或CPU绑定.

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


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

使用此dir /b命令将所有文件名的列表传递到.txt文件中.在具有文件的计算机上本地执行,但如果不可能远程执行.然后使用bcp它们将它们批量插入到数据库的表中.然后,您可以在单个SQL查询中执行快速存在检查,该查询将进行高度优化.你将获得一个哈希加入.

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



2> CodeCaster..:

瓶颈最可能是网络流量,或者更具体地说:SMB流量.您的计算机会与SMB通信以从网络存储中检索文件信息.SMB流量"很蹩脚",您需要一些消息来检查文件的存在以及您是否有权阅读它.

对于它的价值,在我的网络上,我可以通过SMB查询每秒大约一百个文件的存在,而递归列出15K文件需要10秒.

什么更快的检索远程目录事先列出的.如果目录结构是可预测的 - 并且存储在这些目录中不包含许多不相关的文件,那么这将是微不足道的.

然后你的代码将如下所示:

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

foreach (var fileToCheck in filesFromDatabase)
{
    fileToCheckExists = filesOnNetwork.Contains(fileToCheck);
}

如果网络上的文件多于您需要检查的文件,则可能会产生不利影响,因为填写和搜索filesOnNetwork将成为您的应用程序的瓶颈.


@CodeCaster我正避免回答这个问题.我们所能给他的只是一些想法.我已经给出了我的意见.在这种情况下,OP必须自己做很多工作.
推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有