【问题标题】:Why do linq search has a huge difference in efficiency when I use string and array especially for large data?为什么当我使用字符串和数组特别是大数据时,linq搜索的效率会有很大差异?
【发布时间】:2014-11-12 14:27:22
【问题描述】:

我想搜索包含关键字的学生姓名,一开始我通过逗号分隔的关键字,但我发现搜索时间太长了。但是当我将这些关键字转换为数组时,它是真实的快。为什么linq搜索效率差异很大?是数组还是linq的原因?

使用字符串搜索

var keyWord="Lyly,Tom,Jack,Rose"; //and so on,more than 500 names
var student= Context.Students.Where(i => keyWord.Contains(i.Name));//very slow

使用数组搜索

var keyWord="Lyly,Tom,Jack,Rose"; //and so on,more than 500 names
 var keyWordArray=keyWord.split(',');
var student= Context.Students.Where(i => keyWordArray.Contains(i.Name));//fast

【问题讨论】:

  • 在您的第一个示例中,我们看不到您如何从关键字字符串传递到站集合
  • 谢谢。我已经更新了。
  • 拜托,你能多贴一些你的代码吗?根据我们所看到的——当然它是不完整的——我可以在第一个示例中告诉您,您的代码正在将 Contains 函数应用于一个非常大的字符串,因此这很容易成为缓慢的根源

标签: c# linq


【解决方案1】:

是的,这是因为数组。 Linq 数据库提供程序可以将带有数组的数据转换为非常有效的形式。

即,在数据库终端中,

第一个查询将使用SQL Like,但第二个查询将使用SQL IN。它们之间的差异是巨大的。

SQL Like 必须对整个字符串进行全面扫描,以满足一名学生。

SQL IN 必须不进行任何扫描,因为 IN 正在使用隐藏的集合。

请注意,这仅适用于数据库。如果您使用Linq2Object 对上述比较进行基准测试,您可能不会看到任何差异,可能是毫秒。

如果你想让Linq2Object也有性能,你应该使用HashSet,像这样:

var keyWord = "Lyly,Tom,Jack,Rose";
var keyWordSet = new HashSet<string>(keyWord.split(','));

var students = Context.Students
                .ToList()
                .Where(i => keyWordSet.Contains(i.Name));

【讨论】:

  • 嗨,@Chris Eelmaa,为什么 Linq2Object 看不到任何差异?但 ronMan84 表示,LINQ to Objects 也会出现同样的差异。
  • @Lyly:看不出有什么区别,因为 linq2objects 是一步一步执行的,一个语句一个语句。与具有整个查询概述的 Linq2Sql 相比,可以将其转换为更有效的 SQL。 Linq2Sql 可以看到“整个”linq 查询的方式是它们使用 IQueryable&lt;T&gt; 构造,与 Linq2Objects 使用的 IEnumerable&lt;T&gt; 相反。从本质上讲,Linq2Objects 并没有“翻译”任何东西,它正在执行它被告知要做的事情。
  • 嗨,@Chris Eelmaa,Linq2Sql 可以看到“整个”linq 查询的方式是,他们使用的是 IQueryable 构造,与 Linq2Objects 使用的 IEnumerable&lt;T&gt; 相反。是吗?表示array 使用IQueryable&lt;T&gt;HashSet 使用IEnumerable&lt;T&gt;?
【解决方案2】:

主要区别在于查询转换,其中String.Contains 变为LIKEList.Contains 变为IN(就像@ChrisEelmaa 所说)。

同样的差异也会出现在 LINQ to Objects 中,尽管每个差异的发生速度都比您在此处(调用数据库)的速度快。 String.Contains() 从头到尾遍历整个字符串,然后返回它是否找到了某些东西。相反,List.Contains() 执行完全线性搜索,并在找到匹配项后返回。因此,最多List.Contains() 将是相同的速度,但对于大多数元素来说它会更快。

两者的 MSDN 链接:

String.Contains()

List.Contains()

【讨论】:

  • IronMan84:这不是“相同的区别”。 String.Contains() 找到匹配项后立即停止,如果找到某些内容,它没有理由遍历整个字符串。为什么要呢?他们都执行线性搜索并尽快停止。另外,请注意,在处理数组时,调用不会绑定到 List.Contains()
  • 唯一的区别是每个元素如何与正在搜索的值进行比较。在 LINQ 的第一个版本中,一旦字符不匹配,它就会停止,但是,数组 one 有额外的好处:它会“跳过”不具有相同长度 + 相同内容的数组元素,这将快点。关键是:不同之处在于 Linq2Sql 将生成使用set 的查询,因此不会有“线性搜索”。在这个例子中(使用名称),我确信 Linq2Objects 的差异将是毫秒。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 2012-01-28
  • 1970-01-01
相关资源
最近更新 更多