EF Core在内存中而不是在SQL中执行GroupBy操作所需的解决方法
我正在使用Entity Framework Core 1.1.0(此时升级不是一个选项,因为在以后的版本中会发生重大变化)。 我的查询格式如下:
var q = db.MyTable .GroupBy(t => new { t.Field1 }) .Select(g => new { g.Key.Field1, MaxField2 = g.Max(x => x.Field2) }) .ToList();
在测试代码中,这很好用并返回预期的数据。 但是当使用真实数据部署到真实环境时,它会超时。 为什么? 好吧,我在SQL服务器上放了一个嗅探器,这是实际的SQL:
SELECT [t].[Field1], [t].[Field2], [t].[Field3], [t].[Field4], [t].[Field5] FROM [dbo].[MyTable] AS [t] ORDER BY [t].[Field1]
哦。 好吧,这可以解释它。 EF只是将查询编译到.GroupBy()
到SQL,因此尝试将表的全部内容(此时写入大约1700万条记录)加载到内存中,其余的分组和排序是假设的在记忆中完成。
有任何建议如何重写这个查询,以便在SQL中完成繁重的工作?
EF Core 1.1.0不支持: https : //github.com/aspnet/EntityFramework/issues/2341
LINQ的GroupBy()运算符有时可以转换为SQL的GROUP BY子句,特别是在投影中应用聚合函数时。
遗憾的是,即使在EF Core 2.0.0中也不会支持它。
正如@xanatos指出的那样,EF Core 1.1.0(甚至不是2.0.0)都不支持。 但是,使用文字SQL有一种解决方法:
var q = db.MyTable .FromSql("select t.* from " + " (select distinct Field1 from MyTable) t0 " + "cross apply " + " (select top 1 t.* from MyTable t " + " where t.Field1 = t0.Field1 " + " order by t.Field2 desc) t") .Select(t => new { t.Field1, MaxField2 = t.Field2 }) .ToList();
不是我希望的解决方案,但它有魅力。
正如您在本博客文章中看到的那样, GROUP BY
将在2.1中得到支持,尚未发布,但预计 2017 年第一季度至 2017 年 第四季度 。