0

我有一个要解析到我的数据库的 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 分钟。

你知道我该如何改进它并让它变得更好吗?

我有点绝望。

谢谢!

4

4 回答 4

0

您可以通过在添加元素之前检查该元素是否存在于数据库中来解决。

并且您想使用 xml 阅读器,以便在阅读时进行解析(以获得最佳性能)

于 2012-04-19T19:20:57.787 回答
0

看起来你正在与两件事作斗争:

  1. 对于此类任务,XML 是一个糟糕的选择(但我知道这可能不是您的选择)
  2. 将整个文档读入XDocument(or XmlDocument) 是昂贵且不必要的

要摆脱 (2),请尝试使用较低级别的方法XmlReader(可能还不够),或者使用 Java-neseSAX或 Perl-ish等更低级别的方法,它们可以在XML:Twig不构建文档结构的情况下为您提供基于事件的 XML 解析 -但是我不知道.net 的此类库。有一个用于 .NET 的 SAX 解析器端口,但我不知道它有多好。

当然,您可以节省很多时间来保存以前解析过的文档中的数据并只解析新的(但我相信您知道这一点)

于 2012-04-19T19:29:40.063 回答
0

您现在要做的是,对于 dict1 中的这些数百万个事件中的每一个,您迭代 dict2 中的数百万个事件,将 dict1 中的每个事件与 dict2 中的每个事件进行比较。这使得成千上万的比较!这不是必需的。将所有事件从第一个 XML 放入字典。然后对于第二个 XML 中的每个事件,查看字典中第一个 XML 中是否也存在相同的事件。如果是,请将其删除。在字典中搜索比在第一个 XML 中搜索数百万个事件要快得多,并且也会使您的程序更快。

于 2012-04-19T20:33:25.020 回答
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;

对,就是那样。我已经在一些虚拟数据广告上对此进行了测试,它运行良好。

文档1:

<doc>
  <event>bar</event>
  <event>foo</event>
</doc> 

初始文档2:

<doc>
  <event>foo</event>
  <event>qaz</event>
</doc> 

最终文档2:

<doc>
  <event>qaz</event>
</doc>
于 2012-04-20T05:10:30.643 回答