【问题标题】:LINQ select with many ToList inside takes too much time内部有许多 ToList 的 LINQ 选择需要太多时间
【发布时间】:2020-01-11 21:54:42
【问题描述】:

我在select 下方使用LINQ 查询需要太多时间如果我在SelectAsQueryable 上执行ToList

接近 1

大约需要 10 秒

这是我使用不同 ToList() 的数据的最简单表示形式

MYTABLE 下方与COLUMN(another table) 具有一对多关系,Description 字段

使用分析器查询对所有 ToList 都有 UNION ALL 但查询本身在 100 毫秒内执行,似乎需要通过 C# 解析

  // Project into usable data and enumerate
            var enumerated = await this.Context.MYTABLE.AsQueryable().Where(some condition).Select(x => new
            {
                Study1 = x.COLUMN.Select(j => j.Description1).ToList(),
                Study2 = x.COLUMN.Select(j => j.Description2).ToList(),
                Study3 = x.COLUMN.Select(j => j.Description3).ToList(),
                Study4 = x.COLUMN.Select(j => j.Description4).ToList(),
                Study5 = x.COLUMN.Select(j => j.Description5).ToList()
            }).ToListAsync(cancellationToken);

            var results = enumerated.Select(o => new
            {
                Result1 = string.Join(", ", o.Study1),
                Result2 = string.Join(", ", o.Study2),
                Result3 = string.Join(", ", o.Study3),
                Result4 = string.Join(", ", o.Study4),
                Result5 = string.Join(", ", o.Study5),
            }).ToList();

            return results;

方法 2

大约需要 2 秒

使用 profiler 查询与之前相比非常小,大约 1/5 行

// Project into usable data and enumerate
        var enumerated = await this.Context.MYTABLE.AsQueryable().Where(some condition).Select(x => new
        {
            x.COLUMN
        }).ToListAsync(cancellationToken);

        var results = enumerated.Select(o => new
        {
            Result1 = string.Join(", ", o.COLUMN.Select(j => j.Description1).ToList()),
            Result2 = string.Join(", ", o.COLUMN.Select(j => j.Description2).ToList()),
            Result3 = string.Join(", ", o.COLUMN.Select(j => j.Description3).ToList()),
            Result4 = string.Join(", ", o.COLUMN.Select(j => j.Description4).ToList()),
            Result5 = string.Join(", ", o.COLUMN.Select(j => j.Description5).ToList()),
        }).ToList();

        return results;

为什么 Approch 2 花费的时间更少,查询也比 1 更简单?

有什么建议可以提高LINQ 的性能

编辑

我注意到在 Approch 2 中,它会多次调用 database 以用于后续的 ToList(),但仍然通过所有这些计算,Database 在几毫秒内检索,而 C# 需要更多时间。

方法 3

这也是2s

我刚刚在 Approch 1 中首先做了ToList

 // Project into usable data and enumerate
  var enumerated2 =  await this.Context.MYTABLE.AsQueryable().Where(some condition).ToListAsync(cancellationToken);

            var enumerated = enumerated2.Select(x => new
            {
                Study1 = x.COLUMN.Select(j => j.Description1).ToList(),
                Study2 = x.COLUMN.Select(j => j.Description2).ToList(),
                Study3 = x.COLUMN.Select(j => j.Description3).ToList(),
                Study4 = x.COLUMN.Select(j => j.Description4).ToList(),
                Study5 = x.COLUMN.Select(j => j.Description5).ToList()
            }).ToList()

            var results = enumerated.Select(o => new
            {
                Result1 = string.Join(", ", o.Study1),
                Result2 = string.Join(", ", o.Study2),
                Result3 = string.Join(", ", o.Study3),
                Result4 = string.Join(", ", o.Study4),
                Result5 = string.Join(", ", o.Study5),
            }).ToList();

            return results;

我不明白为什么Approch 3Approch 1 花费的时间更少,唯一的区别是执行ToList 方法。

【问题讨论】:

  • 你为什么要在StudyX 上给.ToList() 打两次电话?一次进入第一次选择,然后再次进入结果选择。
  • @John 问题已更新
  • 实体框架?实体框架核心?
  • @Jota.Toledo 实体框架

标签: c# performance linq profiling


【解决方案1】:
  1. 为什么要打两次.ToList()?删除第一个,这会有所帮助。
  2. 尝试使用.Include("Tablename")。你可以在这里阅读:https://medium.com/@lucavgobbi/improving-performance-with-linq-b478cd77d105

这大概就是你所面临的所谓“n+1 问题”。你可以在这里阅读:https://www.brentozar.com/archive/2018/07/common-entity-framework-problems-n-1/

【讨论】:

  • 我尝试了.Include("COLUMN").Include("COLUMN.Description1") 仍然没有运气。
  • 您不应该在 Include(..) 中写入列名。应该有表的名称。您需要“包含”执行查询所需的所有表。类似: .Unclude("Table1").Unclude("Table2") 等。我编辑了我的答案并包含一个描述您面临的问题的链接。检查一下。
  • 嗨 @Sofia 感谢您的帮助,但使用 Include 并没有为我带来任何性能提升。
  • 很抱歉听到这个消息。查询似乎并不复杂。您是否尝试过执行原始 SQL 查询?
  • 是的,原始 SQL 快得多(在 200 毫秒内)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2020-06-15
  • 2011-09-23
相关资源
最近更新 更多