【问题标题】:Optimizing orderby sum in LINQ and Entity Framework在 LINQ 和实体框架中优化 orderby sum
【发布时间】:2018-05-29 03:39:21
【问题描述】:

我编写了一个 LINQ 查询,它使用 Sum 扩展方法在 Entity Framework Core (.NET Core 2.0.7) 数据库上下文上执行 orderby。它在小型示例数据库上运行良好,但是当针对约 100,000 个条目的较大数据库运行时,它变得明显更慢并且使用更多 CPU。我在下面粘贴了相关代码。有没有办法更快地执行Sum? (它本质上是任意数量的元组的加权平均值)。

var iqClientIds = (from stat in context.Set<EFClientStatistics>()
    join client in context.Clients
    on stat.ClientId equals client.ClientId
    group stat by stat.ClientId into s
    orderby s.Sum(cs => (cs.Performance * cs.TimePlayed)) / s.Sum(cs => cs.TimePlayed) descending
    select new
    {
          s.First().ClientId,
    })
    .Skip(start)
    .Take(count);

谢谢!

【问题讨论】:

  • 您可以尝试使用 EF Core 2.1 (2.1.0 Early Access Downloads),因为
  • 感谢您的建议@martin-ullrich。但是,2.1 似乎没有完整的 MySQL 提供程序。 MySQL.Data 和 Pomelo.EntityFramework.MySql 都无法正常工作。
  • 请注意,如果在查询的orderby / select 部分中没有使用很多其他字段,则对查询进行早期选择可以通过减少数据量来提高性能被group...by 拉进来(例如group new { stat.ClientId, stat.Performance, stat.TimePlayed } by...)。

标签: linq .net-core entity-framework-core


【解决方案1】:

EF Core 2 处理 GroupJoin 并转换为 SQL,您的查询可以转换为使用它:

var iqClientIds = (from client in context.Clients 
                   join stat in context.Set<EFClientStatistics>() on client.ClientId equals stat.ClientId into sj
                   orderby sj.Sum(s => (s.Performance * s.TimePlayed)) / sj.Sum(s => s.TimePlayed) descending
                   select sj.First().ClientId
                  )
                  .Skip(start)
                  .Take(count);

注意:我将结果 (select) 简化为不为单个值创建匿名对象。

【讨论】:

  • 使用您建议的变体,我能够提高性能。我只需要等待 2.1 兼容的 MySQL 提供程序,直到我再次使用 group by。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
相关资源
最近更新 更多