• 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版本的时候需要特别注意。

  • 相关阅读:
    使用PHP模拟post提交数据
    window.event.keycode值大全
    php采集
    自己写的一个简单PHP采集器
    php如何实现定时任务,php定时任务方法,最佳解决方案,php自动任务处理
    关于delphi软件运行出现Invalid floating point operation的错误的解决办法
    delphi编程创建桌面快捷方式
    BCB直接访问硬件端口和物理内存
    delphi winio 输入
    总是说spring难学?来看完这些spring的注解及其解释,真香!
  • 原文地址:https://www.cnblogs.com/seekdream/p/13210440.html
Copyright © 2020-2023  润新知