【问题标题】:very slow IOrderedQueryable ToList()非常慢的 IOrderedQueryable ToList()
【发布时间】:2012-12-18 07:09:03
【问题描述】:

我有一个查询,它返回带有过滤孩子的父母:

 Context.ContextOptions.LazyLoadingEnabled = false;
  var query1 = (from p in Context.Partners
                          where p.PartnerCategory.Category == "03"
                                || p.PartnerCategory.Category == "02"
                          select new
                                     {
                                         p,
                                         m = from m in p.Milk
                                             where m.Date >= beginDate
                                                   && m.Date <= endDate
                                                   && m.MilkStorageId == milkStorageId
                                             select m,
                                         e = p.ExtraCodes,
                                         ms = from ms in p.ExtraCodes
                                              select ms.MilkStorage,
                                         mp = from mp in p.MilkPeriods
                                              where mp.Date >= beginDate
                                                    && mp.Date <= endDate
                                              select mp
                                     }).Where(
                                         p =>
                                         p.p.ExtraCodes.Select(ex => ex.MilkStorageId).Contains(
                                             milkStorageId) ).OrderBy(p => p.p.Name);
 var partners = query1.AsEnumerable().ToList();

查询返回 200 条记录,从 IOrderedQueryable ToList() 转换非常慢。为什么?

在 sql server management studio 中分析查询后,我注意到查询执行时间为 1 秒并返回 2035 条记录。

【问题讨论】:

  • 你能发布分析器的详细信息吗?因为你确实运行了一个分析器,不是吗?

标签: c# linq entity-framework


【解决方案1】:

造成这种情况的原因可能有很多,如果没有任何分析器信息,这只是猜测工作,即使是深谙代码和领域的人所做的受过高等教育的猜测工作也常常是错误的。

您应该分析代码,因为瓶颈很可能在数据库中,所以按照@Likurg 的建议获取命令文本并在数据库中进行分析。您可能缺少一个或多个索引。

你也可以对查询本身做一些事情,如果没有别的东西可以让它更容易理解并且可能更快

例如

p.p.ExtraCodes.Select(ex => ex.MilkStorageId).Contains(milkStorageId)

真的

p.p.ExtraCodes.Any(ex => ex.MilkStorageId == milkStorageId)

并且可以移动到第一个 where 子句可能减少您创建的匿名类型对象的数量。也就是说,最有可能的情况是,您在比较中使用的众多字段之一没有索引,这可能会导致对结果集中的每个元素进行大量表扫描。

索引可能加快速度的一些字段是

  • p.p.名字
  • m.Date
  • m.MilkStorageId
  • mp.日期
  • PartnerCategory.Category

【讨论】:

    【解决方案2】:

    它很慢的原因是因为当您执行ToList 时,那是实际执行查询的时间。这称为deferred execution

    你可能会看到:LINQ and Deferred Execution

    我认为在将其转换为列表时您不需要做AsEnumerable,您可以直接这样做:

    var partners = query1.ToList();
    

    【讨论】:

    • 哈比布,谢谢您的回复。无论如何,如果没有 AsEnumerable,我的表现非常糟糕。
    • @Alex,如果不改进底层查询恐怕无法提高迭代查询的性能,即使用 ToList 或 ToArray 等。
    【解决方案3】:

    首先使用this查看生成的查询

    Context.GetCommand(query1).CommandText;
    

    然后在 db 中调用此命令。并检查分析器读取了多少条记录。

    【讨论】:

      猜你喜欢
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      相关资源
      最近更新 更多