使用多个include语句优化linq查询

时间:2019-06-17 07:43:01

标签: performance linq query-optimization

linq查询大约需要20秒才能对某些数据执行。将linq转换为sql时,有3个嵌套的联接可能需要花费更多的时间来执行。我们可以优化以下查询吗?

var query = (from s in this.Items 
             where demoIds.Contains(s.Id)      
             select)
             .Include("demo1")
             .Include("demo2")
             .Include("demo3")
             .Include("demo4");

return query;

期望在3-4秒内执行查询,现在100个demoIds大约需要20秒。

3 个答案:

答案 0 :(得分:0)

就您的代码而言,这似乎是获得所需内容的最佳方法(假设两次Include"demo3"是本示例的错字。)

但是,您使用的数据库将有一种优化查询或基础数据结构的方法。使用数据库提供者必须使用的任何工具来获取查询的执行计划,并查看花费了很多时间的地方。您可能缺少一两个索引。

答案 1 :(得分:0)

我建议延迟加载或加入查询。

此查询可能是SQL输出;

(SELECT .. FROM table1 WHERE ID in (...)) AS T1
   (INNER, FULL) JOIN (SELECT .. FROM table2) AS T2 ON T1.PK = T2.FOREIGNKEY
   (INNER, FULL) JOIN (SELECT .. FROM table3) AS T3 ON T1.PK = T3.FOREIGNKEY
   (INNER, FULL) JOIN (SELECT .. FROM table4) AS T4 ON T1.PK = T4.FOREIGNKEY

但是,如果可以使用延迟加载,则无需使用Include()函数。延迟加载将解决您的问题。

其他情况下,您可以使用联接查询来编写

var query = from i in this.Items.Where(w=>demoIds.Contains(w.Id))
            join d1 in demo1 on i.Id equals d1.FK
            join d2 in demo2 on i.Id equals d2.FK
            join d3 in demo3 on i.Id equals d3.FK
            select new ... { };

这两个解决方案可以解决您的所有问题。 如果问题仍然存在,我强烈建议您执行存储过程。

答案 2 :(得分:0)

对于包含15个以上“包含”语句并在7分钟内生成2M +行的结果的查询,我遇到了类似的问题。

最适合我的解决方案是:

  1. 禁用延迟加载
  2. 已禁用自动检测更改
  3. 将大查询分成小块

可以在下面找到一个示例:

public IQueryable<CustomObject> PerformQuery(int id) 
{
 ctx.Configuration.LazyLoadingEnabled = false;
 ctx.Configuration.AutoDetectChangesEnabled = false;

 IQueryable<CustomObject> customObjectQueryable = ctx.CustomObjects.Where(x => x.Id == id);

 var selectQuery = customObjectQueryable.Select(x => x.YourObject)
                                                  .Include(c => c.YourFirstCollection)
                                                  .Include(c => c.YourFirstCollection.OtherCollection)
                                                  .Include(c => c.YourSecondCollection);

 var otherObjects = customObjectQueryable.SelectMany(x => x.OtherObjects);

 selectQuery.FirstOrDefault();
 otherObjects.ToList();

 return customObjectQueryable;
 }

需要IQueryable以便在服务器端进行所有过滤。 IEnumerable将在内存中执行过滤,这是一个非常耗时的过程。实体框架将修复内存中的所有关联。