【问题标题】:LINQ performance question when joining IEnumerable with IQueryable使用 IQueryable 加入 IEnumerable 时的 LINQ 性能问题
【发布时间】:2018-11-15 19:37:59
【问题描述】:

我在这段代码中遇到了一些严重的 LINQ 速度问题(变量名已更改)

var A = _service.GetA(param1, param2); // Returns Enumerable results

var results = (from b in _B.All() // _B.All() returns IQueryable
        join c in _C.All() on b.Id equals c.Id // _C.All() returns IQueryable
        join a in A on a.Id equals c.Id
        where b.someId == id && a.boolVariable // A bool value
        select new
        {
          ...
        }).ToList();

即使 B 和 C 表中的行数少于 100k,此 LINQ 也需要 10 多秒才能执行。

我对此进行了研究,通过反复试验,通过将代码更改为以下代码,我设法将 LINQ 执行时间缩短到 200 毫秒:

var A = _service.GetA(param1, param2).Where(a => a.boolVariable); // Returns Enumerable results

var results = (from b in _B.All() // _B.All() returns IQueryable
        join c in _C.All() on b.Id equals c.Id // _C.All() returns IQueryable
        join a in A on a.Id equals c.Id
        where b.someId == id
        select new
        {
          ...
        }).ToList();

所以我的问题是,为什么这个简单的更改会对 LINQ 性能产生如此巨大的影响?唯一的变化是我预先过滤了 Enumerable 列表,A 枚举在过滤前大约有 30 项,过滤后有 15 项。

【问题讨论】:

  • 当您对原始代码运行 SQL 跟踪时,提交到数据库的是什么?当您为最终代码运行 SQL 跟踪时,提交到数据库的是什么?
  • 我猜a.boolVariableb.someId == id 的顺序可能会颠倒之类的。
  • 请更新您的问题以准确显示在这两种情况下提交到数据库的内容。我认为您忘记编辑您的问题以包含它。
  • 请同时向我们展示GetA的源代码。
  • @Dadoss 如果您不愿意显示源代码,您的问题很可能会被关闭。显示minimal reproducible example 至关重要。许多提出问题的人认为某些事情无关紧要。而且它们通常是不正确的。这是至关重要的。当我们试图帮助你时,你把我们的手绑在背后。错误是几乎可以肯定,因为该方法返回IEnumerable

标签: c# .net performance linq


【解决方案1】:

在您的第一个场景中:首先它连接 A 中需要很长时间才能连接的所有记录,然后过滤掉 a.boolVariable

在您的第二种情况下,在加入之前,您有一个较小的 A 记录子集 - 当然这将花费更少的时间来加入。

【讨论】:

  • 即使您有 10 条记录与 5 条记录,这也意味着那些 B 和 C 中所有其他 100K 记录的 10 倍与 100K 的 5 倍。更不用说之后所有这些记录都需要过滤掉(过滤 10 条记录 vs 10000 条记录)。
  • @Dadoss 所以基本上当你混合 IQueryable 和 IEnumerable 时,会有一条灰线表示什么将在 sql server 上执行,它不会在 sql server 上执行。现在,通过在 where 子句(第一种情况)中使用 IENumerable,它将强制部分查询在内存中完成。但在第二种情况下,实体框架将通过将最后一个连接变为虚拟选择或完全将其删除并将其添加为 where (in) 来使 sql 更好一点。所有这些只是我多年来尝试的各种 linq 查询中的推测
猜你喜欢
  • 2020-10-13
  • 2019-04-23
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多