zoukankan      html  css  js  c++  java
  • EFCore2.2使用Include进行查询并排序时性能问题

    背景

    最近在使用EFCore2.2进行查询后并排序的过程中发现了一个问题,就是查询的过程使用了Include后代码生成的SQL不符合预期,并且性能上面有很大的问题,借此写一篇文章来进行分析。

    1.1 EFCore语句

    LinQ语句 _ = _repairContractRepository.GetAll().Include(r => r.RepairContractWorkItems).OrderByDescending(r => r.CreateTime).Take(20).ToList();
    

      在上面的例子中_repairContractRepository表示的是实体RepairContract的仓储,在代码中的定义是:private readonly IRepository<RepairContract, Guid> _repairContractRepository;另外一个RepairContract对应多个RepairContractWorkItem,两个实体之间是一对多的关系,在EFCore中通过Include方法来一次性查询出关联的对象,后面我们将查询的结果按照主单的CreateTime进行排序并取前20条,我们来看看这条语句生成的SQL是否符合预期。

    1.2 生成的SQL语句  

    SELECT TOP (20) r.*
    FROM [RepairContract] AS [r]
    ORDER BY [r].[CreateTime] DESC, [r].[Id]
    

      明明只是按照CreateTime进行排序,为什么后面会加一个[r].[Id],这个问题该怎么解释,多了一个按照主单Id升序排列到底有什么影响,我们来看看具体的统计信息。

      图一 加了导航属性生成SQL及部分参数统计

       在我们的数据库中主单RepairContract大概有26万条数据,我们已经在CreateTime上面创建了索引,按照道理不会这么慢,那我们试着去掉[r].[Id]来看看到底有什么差别。

    图二 未加导航属性生成SQL及部分参数统计

       结果查询的时间从5723毫秒一下子降到了3毫秒,性能产生了巨大的提升,为什么会产生这个原因呢?事后发现是因为在查询的过程中使用了导航属性Include,去掉这个导航属性之后就能够生成符合我们预期的SQL语句了,所以在使用Include查询并进行排序的过程中一定要注意看最终生成的SQL是否符合预期,至于为什么加了导航属性后进行排序会多出一部分排序,这个也没有发现原因。

    结论

      其实对于这个问题早在EF框架的时候就有这个问题,你可以看看这篇文章,现阶段的解决方式只有在使用导航属性后尽量不要去Order By操作,如果真要进行排序操作,那么就不要使用Include的导航属性来直接进行操作,这个在使用EFCore2.2版本的时候需要特别注意。

  • 相关阅读:
    利用ganymed-ssh2远程执行其它Linux机器上的shell命令
    ZooKeeper 笔记(4) 实战应用之【消除单点故障】
    ZooKeeper 笔记(3) 实战应用之【统一配置管理】
    ZooKeeper 笔记(2) 监听数据变化
    ZooKeeper 笔记(1) 安装部署及hello world
    intellij idea 高级用法之:集成JIRA、UML类图插件、集成SSH、集成FTP、Database管理
    hadoop: hive 1.2.0 在mac机上的安装与配置
    mac 下卸载mysql的方法
    mac OS X Yosemite 上编译hadoop 2.6.0/2.7.0及TEZ 0.5.2/0.7.0 注意事项
    hadoop: hbase1.0.1.1 伪分布安装
  • 原文地址:https://www.cnblogs.com/seekdream/p/13210440.html
Copyright © 2011-2022 走看看