我试图将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); } }
解决方法
尝试这样的事情:
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 举报,一经查实,本站将立刻删除。