我有一个XML解析到我的数据库,这个XML大小约为10MB,它包含数百万个元素。
每30-60秒更新一次,但只有几个元素,而不是全部。
为了以最快的方式解析数据库,我开发了一个函数来从2个XML文件中删除重复元素,这里是代码:
XDocument doc2 = XDocument.Parse(tempDoc.ToString());
var doc1 = new XDocument();
try
{
doc1 = XDocument.Load(bookieName + ".xml");
}
catch
{ }
try
{
var dict1 = doc1.Descendants("event").Select(el => el.ToString()).ToList();
var dict2 = doc1.Descendants("event").Select(el => el.ToString()).ToList();
foreach (var elem in dict1)
{
if (dict2.Contains(elem))
{
if (dict2.Find(x => x == elem).ToString() == dict1.Find(x => x == elem).ToString())
{
doc2.Descendants("event").Where(x => x.ToString() == elem).Remove();
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return doc2;
问题是,它适用于小型XML文件,但对于大型XML文件(10MB),它需要100%的CPU,持续2-5分钟。
你知道我怎样才能改进它并使其更好?
我有点无望。
谢谢!
答案 0 :(得分:0)
您可以通过在添加元素之前检查元素是否存在来解决。
并且您希望使用xml阅读器,以便在阅读时进行解析(以获得最佳性能)
答案 1 :(得分:0)
看起来你正在打两件事:
XDocument
(或XmlDocument
)是昂贵的,没有必要要摆脱(2),尝试使用较低级别的方法XmlReader
(可能不够)或更低级别的方法,如Java-nese SAX
或Perl-ish {{ 1}}它给你基于事件的XML解析而不构建文档结构 - 但是我不知道.net的这些库。有一个port of the SAX parser for .NET,但我不知道知道它有多好。
当然,您可以节省大量时间来保存以前解析过的文档中的数据,并且只解析新文档(但我相信您知道)
答案 2 :(得分:0)
你现在所做的是,对于dict1中的这些数百万个事件中的每一个,你在dict2中迭代数百万个事件,将来自dict1的每个事件与来自dict2的每个事件进行比较。这使得成千上万的比较!这不是必需的。将所有事件从第一个XML放到字典中。然后,对于第二个XML中的每个事件,查看字典是否同样的事件也存在于第一个XML中。如果是,请将其删除。在字典中搜索比在第一个XML中浏览每一百万个事件要快得多,并且会使你的程序更快。
答案 3 :(得分:0)
听起来你只想删除doc2
中的元素,如果它们也存在于doc1
中,而不是相反。
您面临的问题是您的搜索效率非常低。如果您有几百万条记录,那么您可以通过几百万个平方记录进行有效搜索。
相反,您应该使用字典而不是列表来大大加快算法速度。
试试这个:
var dict1 = doc1.Descendants("event").ToDictionary(x => x.ToString(), x => x);
var dict2 = doc2.Descendants("event").ToDictionary(x => x.ToString(), x => x);
var xs = dict1.Keys.Intersect(dict2.Keys).Select(x => dict2[x]);
foreach (var x in xs)
{
x.Remove();
}
return doc2;
是的,就是这样。我已经在一些虚拟数据广告上对此进行了测试,但它运行良好。
DOC1:
<doc>
<event>bar</event>
<event>foo</event>
</doc>
初始doc2:
<doc>
<event>foo</event>
<event>qaz</event>
</doc>
最终的doc2:
<doc>
<event>qaz</event>
</doc>