我有一批大约 13,000 个 XML 文件(每天可能增长数百个),我需要使用 LINQ 过滤和将数据转换为我需要的数据进行处理,并将七种可能的事件类型中的每一种聚合到一个事件类型文件中(见下文)。所以,13k 文件分成 7 个文件。事件类型在 XML 中被很好地描述,因此过滤和聚合相对容易。然后,这些聚合文件将用于使用我已经编写的脚本为我们的数据库创建一个 MySQL 插入语句,该脚本也可以正常工作。
我有功能代码,它正在处理文件,但到目前为止它已经运行了 23 多个小时,看起来可能只完成了一半(?)。我忽略了放入文件计数器,所以我真的不知道,我不愿意再次重新启动它。我可以根据原始文件的大小(360mb 左右)与处理后的文件大小(180mb 左右)来做出有根据的猜测。我预计可能要运行大约六次,直到我们转储这种数据收集方法(使用 XML 文件作为数据库)并过渡到只使用 MySQL,所以我希望我能找到一种更有效的方法来处理文件。如果我不需要的话,我真的不想每次执行都花费 2 天以上的时间。
它在我的机器上本地运行,但仅在 1 HD(我认为是 10k RPM 梭子鱼)上运行。从一个驱动器读取并写入单独的驱动器可能会更快吗?我很确定我的瓶颈是由文件 IO 引起的,我正在打开和关闭文件数千次。也许我可以重构只打开一次阅读并在内存中做所有事情?我知道这会更快,但如果出现问题,我可能会丢失整个文件的数据。我仍然必须打开每个 13k 文件来读取它们、处理它们并写出到 XElement。
这是我正在运行的代码。我正在使用 LINQPad 并将代码作为 C# 语句运行,但如有必要,我可以将其转换为真正的可执行文件。LINQPad 对于这样的原型制作非常方便!请让我知道 XML 的示例是否会使这更容易理解,但乍一看,它似乎并不密切。文件大小从 2k 到 285k 不等,但只有 300 个左右超过 100k,大多数在 25-50k 范围内。
string sourceDir = @"C:\splitXML\results\XML\";//source for the 13k files
string xmlDestDir = @"C:\results\XMLSorted\";//destination for the resultant 7 files
List<string> sourceList = new List<string>();
sourceList = Directory.EnumerateFiles(sourceDir, "*.xml", SearchOption.AllDirectories).ToList();
string destFile = null;
string[] events = { "Creation", "Assignment", "Modification", "Repair", "RepairReview", "Termination", "Test" };
foreach(string eventItem in events)
{
try
{
//this should only happen once the first time through and
//shouldn't be a continuing problem
destFile = Path.Combine(xmlDestDir, eventItem + "Uber.xml");
if (!File.Exists(destFile))
{
XmlTextWriter writer = new XmlTextWriter( destFile, null );
writer.WriteStartElement( "PCBDatabase" );
writer.WriteEndElement();
writer.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
foreach(var file in sourceList) //roughly 13k files
{
XDocument xd = XDocument.Load(file);
var actionEvents =
from e in xd.Descendants("PCBDatabase").Elements()
select e;
foreach(XElement actionEvent in actionEvents)
{
//this is where I think it's bogging down, it's constant file IO
var eventName =
from e in actionEvents.Elements()
select e.Name;
var eventType = eventName.First();
destFile = Path.Combine(xmlDestDir, eventType + "Uber.xml");
//another bottle neck opening each file thousands of times
XElement xeDoc = XElement.Load(destFile);
xeDoc.Add(actionEvent);
//and last bottle neck, closing each file thousands of times
xeDoc.Save(destFile);
}
}