【问题标题】:How I can Optimize this linq query我如何优化这个 linq 查询
【发布时间】:2014-07-02 21:13:24
【问题描述】:

有没有办法优化这个查询?

_alternatives.Cast<AlternativePartName>()
                                .Where(alt => original.ToLower() == alt.CompName)
                                .Select(alt => alt.AltCompName).ToList();

我正在分析我的应用程序,这段代码是 196 毫秒的瓶颈之一,但它执行了很多次。

【问题讨论】:

  • 不优化查询,而是缓存结果?也就是说,您是否将提供程序插入日志文本编写器,以查看实际执行了哪些查询?
  • 此 linq 查询是否针对数据库运行?
  • @ Lorentz Vedeler 不,它反对 ArrayList
  • 可以不使用.ToList()吗?而是枚举后续代码中的项目。
  • 这是某种键/值存储吗?您使用的是数据库还是这只是对象?

标签: c# .net linq


【解决方案1】:

不要为每个项目调用ToLower,而是只调用一次

var lower = original.ToLower();

_alternatives.Cast<AlternativePartName>()
              .Where(alt =>  lower == alt.CompName)
              .Select(alt => alt.AltCompName).ToList();

【讨论】:

  • 也可以用IEnumerable代替ToList()
  • IEnumerable 是一个接口。如果您将类型更改为 IEnumerable,仍然会创建一个 List 对象并将其分配给 IEnumerable。 IEnumerable 本身不能容纳任何对象。
  • @Selman22:即使我在集合上调用 ToLower(),它仍然可以在集合中的每个对象上工作,不是吗?
  • @sloth:我明白你的意思。您的意思是,在某些情况下我们可能不会迭代结果,在这些情况下不需要 ToList。同意,我认为这将是一个微不足道的案例,但重点是。
  • @SidharthPanwar 是的,它会将每个项目与original 的最低版本进行比较,而不是每次都将原始版本转换为小写。
【解决方案2】:

您应该尝试在 .AsParallel() 中使用更多内核 - 这可能是对长字符串的大型列表的改进

string lower = original.ToLower();
_alternatives.Cast<AlternativePartName>()
              .AsParallel()
              .Where(alt =>  lower == alt.CompName)
              .Select(alt => alt.AltCompName)

【讨论】:

  • 这是一个不错的选择,IMO。但请确保您的数据集足够大以利用并行化。对于较小的集合,它会进一步减慢查询速度。这是一个很好的链接 - dotnetperls.com/asparallel
【解决方案3】:

我假设“original”和“CompName”是字符串。如果是,那么您应该执行以下操作:

_alternatives.Cast<AlternativePartName>()
                                .Where(alt => String.Equals(original, alt.CompName, StringComparison.OrdinalIgnoreCase))
                                .Select(alt => alt.AltCompName).ToList();

【讨论】:

  • 为什么你认为它会更快?
  • 您将节省在集合中的每个对象上运行 ToLower() 的成本。您的集合越大,您在运行 ToLower() 上花费的时间就越多。此外,比较字符串的标准方法是使用 String.Equals 而不是 == 运算符。
【解决方案4】:

使用正确的数据结构是提高性能的最佳方式。在您的情况下,如果您使用以CompName 为键并以AltCompNames 为项目的列表的字典会更好。查找会非常快,因为没有迭代,只有单个查找。并且通过添加和删除项目来保持这种简单的结构是最新的应该不是一个大问题。

【讨论】:

    【解决方案5】:

    只调用一次orignal.ToLower() 不会改变任何实际性能。

    尝试使用例如如果您有足够的 CPU-Power,并行 LINQ 可以更快地获得结果。

    【讨论】:

      【解决方案6】:

      我不太擅长点语法,但是这个

      .Select(alt => alt.AltCompName)
      

      结合这个

      _alternatives.Cast<AlternativePartName>()
      

      可以通过选择直接制作 AlternativPartName 来实现

      select new AlternativePartName(){...}
      

      【讨论】:

        猜你喜欢
        • 2011-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-22
        相关资源
        最近更新 更多