【问题标题】:Finding strings that are not in DB already查找已经不在数据库中的字符串
【发布时间】:2012-01-29 20:56:22
【问题描述】:

我的应用程序存在一些性能不佳的问题。比较大的操作之一是比较字符串。 我下载了一个字符串列表,大约 1000 - 10000。这些都是唯一的字符串。 然后我需要检查这些字符串是否已经存在于数据库中。 我正在使用的 linq 查询如下所示:

IEnumerable<string> allNewStrings = DownloadAllStrings();

var selection = from a in allNewStrings
                where !(from o in context.Items
                        select o.TheUniqueString).Contains(a)
                select a;

我是不是做错了什么,或者我怎样才能让这个过程更快地使用 Linq?

谢谢。

【问题讨论】:

    标签: performance linq optimization


    【解决方案1】:

    您确实为 allNewStrings 中的每个元素查询了 1000 到 10000 次相同的唯一字符串,因此效率极低。

    尝试单独查询唯一字符串,以便执行一次:

    IEnumerable<string> allNewStrings = DownloadAllStrings();
    
    var uniqueStrings = from o in context.Items
                        select o.TheUniqueString;
    
    var selection = from a in allNewStrings
                    where !uniqueStrings.Contains(a)
                    select a;
    

    现在您可以看到可以使用Except 编写最后一个查询,这对于像您的示例这样的集合运算符更有效:

    var selection = allNewStrings.Except(uniqueStrings);
    

    【讨论】:

    • Except() 的性能会比!Contains() 好很多
    • @Magnus:是的,集合运算符比对序列的成员测试更有效。我更新了答案以更清楚地说明它。
    • 感谢这个伟大的解决方案。我最初对此唯一担心的是它现在运行良好,但是当我在 Items 中有 100 万个帖子并且需要将它们全部“下载”到内存中然后进行比较时会发生什么?
    • 这种方法对于大量uniqueStrings来说仍然是合理的,假设你有大内存以避免缓存未命中。
    【解决方案2】:

    另一种解决方案是使用HashSet:

    var set = new HashSet<string>(DownloadAllStrings());
    set.ExceptWith(context.Items.Select(s => s.TheUniqueString));
    

    set 现在将包含不在数据库中的字符串。

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 2013-12-07
      • 2012-01-16
      • 1970-01-01
      • 2017-11-20
      • 2023-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多