微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – HUGE XML文件的问题

我有16个大的xml文件.当我说Large时,我说的是千兆字节.其中一个文件超过8 GB.其中一些超过1 GB.这些是从外部提供商处获得的.

我试图将XML导入数据库,以便我可以将其粉碎成表.目前,我一次将10,000条记录从文件中流入内存并插入blob.我使用SSIS执行脚本任务.对于除8 GB文件之外的所有文件,这实际上非常快.

我无法将整个文件加载到xml文档中.我不能强调这一点.这是迭代1,文件非常庞大,系统只是锁定试图处理这些文件,特别是8 GB.

我运行了当前的“文件分割器”,它花了7个小时来导入xml数据,但仍未完成.它从8 GB文件中导入了363个10,000个记录的块,但仍未完成.

仅供参考,以下是我目前将文件流式传输到内存中的方法(一次10,000条记录).我在http://blogs.msdn.com/b/xmlteam/archive/2007/03/24/streaming-with-linq-to-xml-part-2.aspx找到了代码

private static IEnumerable<XElement> SimpleStreamAxis(string fileName,string matchName) 
        {
            using (FileStream stream = File.OpenRead(fileName))
            {
                using (XmlReader reader = XmlReader.Create(stream,new XmlReaderSettings() { ProhibitDtd = false }))
                {
                    reader.MovetoContent();
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Element:
                                if (reader.Name == matchName)
                                {
                                    XElement el = XElement.ReadFrom(reader) as XElement;
                                    if (el != null)
                                        yield return el;
                                }
                                break;
                        }
                    }

                    reader.Close();
                }

                stream.Close();
            }
        }

因此,它可以在所有文件上正常工作,除了8 GB之外,因为它必须进一步流入文件所需的时间越来越长.

我想要做的是将文件拆分成更小的块,但拆分器需要快速.然后流光和其余的流程可以更快地运行.分割文件的最佳方法是什么?理想情况下,我自己将其拆分为SSIS中的代码.

编辑:

这是使用流式处理方法实际分页我的数据的代码.

connection = (sqlConnection)cm.AcquireConnection(null);

                int maximumCount = Convert.ToInt32(Dts.Variables["MaximumProductsPerFile"].Value);
                int minMBSize = Convert.ToInt32(Dts.Variables["MinimumMBSize"].Value);
                int maxMBSize = Convert.ToInt32(Dts.Variables["MaximumMBSize"].Value);

                string fileName = Dts.Variables["XmlFileName"].Value.ToString();

                FileInfo info = new FileInfo(fileName);

                long fileMBSize = info.Length / 1048576; //1024 * 1024 bytes in a MB

                if (minMBSize <= fileMBSize && maxMBSize >= fileMBSize)
                {
                    int pageSize = 10000;     //do 2000 products at one time

                    if (maximumCount != 0)
                        pageSize = maximumCount;

                    var page = (from p in SimpleStreamAxis(fileName,"product") select p).Take(pageSize);
                    int current = 0;

                    while (page.Count() > 0)
                    {
                        XElement xml = new XElement("catalog",from p in page
                            select p);

                        SubmitXml(connection,fileName,xml.ToString());

                        //if the maximum count is set,only load the maximum (in one page)
                        if (maximumCount != 0)
                            break;

                        current++;
                        page = (from p in SimpleStreamAxis(fileName,"product") select p).Skip(current * pageSize).Take(pageSize);
                    }
                }

解决方法

看起来你每次都在重复读取XML文件,每次使用SimpleStreamAxis中的from p,你都会重新读取并扫描到文件中.同样通过调用Count(),您每次都会走完整页.

尝试这样的事情:

var full = (from p in SimpleStreamAxis(fileName,"product") select p);
int current = 0;

while (full.Any() > 0)
{
    var page = full.Take(pageSize);

    XElement xml = new XElement("catalog",from p in page
    select p);

    SubmitXml(connection,xml.ToString());

    //if the maximum count is set,only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
    full = full.Skip(pageSize);
}

请注意,这是未经测试的,但您应该希望得到这个想法.您需要避免多次枚举文件,像Count()和Take / Skip这样的操作将花费很长时间在8gb xml文件上.

更新:我认为上面的内容仍然会比我们想要的更多次遍历文件,你需要一些更可预测的东西:

var full = (from p in SimpleStreamAxis(fileName,"product") select p);
int current = 0;

XElement xml = new XElement("catalog");
int pageIndex = 0;

foreach (var element in full)
{
    xml.Add(element);

    pageIndex++;
    if (pageIndex == pageSize)
    {
        SubmitXml(connection,xml.ToString());
        xml = new XElement("catalog");
        pageIndex = 0;
    }

    //if the maximum count is set,only load the maximum (in one page)
    if (maximumCount != 0)
        break;

    current++;
}

    // Submit the remainder
if (xml.Elements().Any())
{
    SubmitXml(connection,xml.ToString());
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


原文地址:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx 原文发布日期: 9/19/2005 原文已经被 Microsoft 删除了,收集过程中发现很多文章图都不全,那是因为原文的图都不全,所以特收集完整全文。 目录 前言 CLR启动程序
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采纳和使用,它的确提供了很多的优势也解决了很多的问题,但是我们也知道也并不是银弹,提供优势的同时它也给我们的开发人员和团队也带来了很多的挑战。 为了迎接或者采用这些新技术,开发团队需要更加注重一些流程或工具的使用,这样才能更好的适应这些新技术所
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下PLINQ中的分区。上一篇介绍了并行编程,这边详细介绍一下并行编程中的分区和自定义分区。 先做个假设,假设我们有一个200Mb的文本文件需要读取,怎么样才能做到最优的速度呢?对,很显然就是拆分,把文本文件拆分成很多个小文件,充分利用我们计算机中
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Microsoft为了利用这个硬件特性,于是在Visual Studio 2010 和 .NET Framework 4的发布及以上版本中,添加了并行编程这个新特性,我想它以后势必会改变我们的开发方式。 在以前或者说现在,我们在并行开发的时候可
c语言输入成绩怎么判断等级
字符型数据在内存中的存储形式是什么
c语言怎么求字符串的长度并输出
c语言函数的三种调用方式是什么
c语言中保留两位小数怎么表示
double的输入格式符是什么