【问题标题】:How to speed up this LINQ query with join?如何通过连接加速这个 LINQ 查询?
【发布时间】:2019-12-13 21:04:39
【问题描述】:

我有两个对象模型集合,我正在对每个属性的不平等进行比较。

ObservableCollection<LayerModel> SourceDrawingLayers

...和:

ObservableCollection<LayerModel> TargetDrawingLayers

我收到了关于创建非等值连接 LINQ 查询的一般建议,并让它在我的应用程序中发挥出色的效果,但现在我想加快速度:

var onOffQuery = from target in TargetDrawingLayers
                 from source in SourceDrawingLayers
                 where target.Name == source.Name && target.OnOff != source.OnOff
                 select target;

我的理解是,我将查询乘以源图形中的项目数 * 目标图形中的项目数 * 我填充到 TargetDrawingLayers 中的目标图形数。

我想使用 Join 加速此操作,但我遇到了 != 部分的问题。

我玩过这个:

var newQuery = from source in SourceDrawingLayers
    join target in TargetDrawingLayers
    on target.name
    where target.OnOff != source.OnOff
    select target;

但我在语法上苦苦挣扎。有人可以让我走上正轨吗?

另外,这甚至会显着提高性能吗?

【问题讨论】:

  • target.OnOff != source.OnOff 将是每行不匹配的乘法,这是一个大数据集。
  • 是的,这就是要我死的原因。在我们的网络环境中,每张绘图大约需要 30 秒来建立这种比较。老实说,这还不错,并且会在 QA 上节省大量时间,但如果可能的话,我想把时间缩短。我们的一些套装将包含超过 200 张或更多图纸,因此显然这是我们希望尽量减少的内容。
  • 缓存是一个选项吗?或者您可以每 1 分钟(只是一个示例时间)单独运行一次查询,存储该数据并获取最新的数据集吗?
  • 为什么不在层的创建过程中进行这样的链接呢?或者甚至在一个单独的线程上可能订阅可观察集合的事件并将它们添加到后台进程中?通过放置public object Tag { get; set; } 甚至直接命名的类,可以完成链接,并且在需要时只需引用Tag。不再需要 30 秒的处理时间,它可以即时完成并根据需要进行访问。

标签: c# linq observablecollection


【解决方案1】:

on target.name 替换为on source.name equals target.name

var newQuery = from source in SourceDrawingLayers
         join target in TargetDrawingLayers
         on source.name equals target.name
         where target.OnOff != source.OnOff
         select target;

在 Linq-to-objects 中,连接将在连接属性上创建一个 Lookup&lt;TKey,TElement&gt;,这将在匹配 sourcetarget 时提高性能。假设这会导致受限结果集,它应该会稍微改进原始代码退出。当然,如果由于name 双方的值范围非常有限,导致很多匹配,那么性能根本不会受到太大影响。

作为参考,请参阅 juharr 在下面的 cmets 中提供的 the link to the Enumerable.cs 源代码。

【讨论】:

  • 谢谢,我会试一试。您认为这会带来有意义的性能提升吗?
  • 如何进行基准测试以帮助确定它是否是性能改进;真正的方法。
  • 具体来说,这将在名称上创建一个哈希,以帮助匹配两个集合中的值(因此名称的类型也会影响这一点,我假设它是一个字符串,它将工作得很好)。然后它将根据 OnOff 的不同过滤这些匹配项。
  • @Çöđěxěŕ 来自问题“但我在语法上挣扎。有人可以让我走上正确的轨道吗?”请告诉我更多关于问题中不涉及语法的信息。
  • @Igor 你可以查看源代码并看到它创建了一个Lookup 以使用referencesource.microsoft.com/#system.core/system/linq/…
【解决方案2】:

也许您需要加入属性NameOnOff 的组合。组合可以表示为ValueTuple

var newQuery = from source in SourceDrawingLayers
               join target in TargetDrawingLayers
               on (source.Name, source.OnOff) equals (target.Name, !target.OnOff)
               select target;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    相关资源
    最近更新 更多