前言

这两天在着实研究EF Core项目当中对于一些查询也没实际去检测,于是想着利用放假时间去实际测试下,结果本文就出来了,too young,too simple,后续博主会从底层翻译表达式树弄起,来从源头了解EF Core,通过本文你会明白不是EF Core团队没做性能优化,而是你根本就没用过而且正在倒退。

EntityFramework Core性能优化初探

简单粗暴直接上代码,给出上下文以及需要用到的测试类,如下:

    public class EFCoreContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(@"Server=.;Database=EFCoreDb;Trusted_Connection=True;"); protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>(pc =>
{
pc.ToTable("Blog").HasKey(k => k.Id); pc.Property(p => p.Name).IsRequired();
pc.Property(p => p.Url).IsRequired();
pc.Property(p => p.Count).IsRequired(); pc.Property(p => p.RowVersion).IsRequired().IsRowVersion().ValueGeneratedOnAddOrUpdate();
});
}
}

你是否像如下去获取分页数据呢,我们来一起瞧瞧:

            var ef = new EFCoreContext();
var blogs = ef.Blogs; var example1 = blogs
.Skip()
.Take()
.ToList(); var example2 = blogs
.Skip()
.Take()
.ToList();

我们通过如下SQL语句来查看查询计划生成的SQL语句:

SELECT
sys.syscacheobjects.cacheobjtype,
sys.dm_exec_query_stats.execution_count,
sys.syscacheobjects.SQL,
sys.dm_exec_query_plan.query_plan FROM sys.dm_exec_query_stats
INNER JOIN sys.dm_exec_cached_plans
ON sys.dm_exec_cached_plans.plan_handle = sys.dm_exec_query_stats.plan_handle
INNER JOIN sys.syscacheobjects ON sys.syscacheobjects.bucketid = sys.dm_exec_cached_plans.bucketid CROSS APPLY sys.dm_exec_query_plan(sys.dm_exec_query_stats.plan_handle)

结果如下:

我们再来看看xml文件中生成的SQL语句是怎样的。

这说明什么问题呢,上述查询计划中生成的SQL语句对于我们上述去取数据首选从第二条取一条,接下来是去取第十条后的十条,同时上述SQL语句而是声明了两个变量,换言之,上述两条语句查询最终在第一次查询后SQL查询计划进行了缓存,下次再去取数据时直接调用此SQL语句以此达到重用的目的,下面要是我们进行如下改造,结果会怎样呢?

            var ef = new EFCoreContext();
var blogs = ef.Blogs; var count = ;
var example1 = blogs
.Skip(count)
.Take(count)
.ToList(); count = ;
var example2 = blogs
.Skip(count)
.Take(count)
.ToList();

结果经过上述改造利用变量的形式和直接赋值的形式是一致的,没有什么可讲的,下面我们再来讲述另外一种情况。请继续往下看。

            var ef = new EFCoreContext();
var blogs = ef.Blogs; var skipTakeWithInt1 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > ).ToList(); var skipTakeWithInt2 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > ).ToList();

看出什么没有,对于上述两条查询则是对应进行了两次SQL查询,这下意识到了其中玄机了吧,下面我们将上述再改造一下:

            var ef = new EFCoreContext();
var blogs = ef.Blogs; var length = ;
var skipTakeWithVariable1 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > length).ToList(); length = ;
var skipTakeWithVariable2 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > length).ToList();

我们利用变量替换值改造后结果生成的SQL语句与上述截然不同,这里同样是声明了长度的变量,你发现没该变量居然和我们声明的变量长度是一致的,有点神奇,如此这样通过变量替换值得方式来达到SQL查询计划重用的目的,说到这里,我们是不是应该回答一下为什么会有这样的情况发生呢。很多东西当你一直没用到时就觉得不会用到压根不用学,其实不然,比如这样,其本质到底是怎样的呢,其实是因为前面我已经讲过【闭包】的原因。

lambda表达式对我们声明的变量进行了捕获然后延长了其生命周期,也就是说将变量类似变成类中一个字段了,类似如下:

    [CompilerGenerated]
public sealed class ExampleClass1
{
public int Length;
} [CompilerGenerated]
public sealed class ExampleClass2
{
public int Length;
}

自动编译生成两个类同时存在两个对于长度的字段。接下来当我们利用变量进行查询就演变了如下这样:

            var ef = new EFCoreContext();
var blogs = ef.Blogs; var length = ;
var example1 = new ExampleClass1() { Length = length };
var skipTakeWithVariable1 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > example1.Length).ToList(); length = ;
var example2 = new ExampleClass2() { Length = length };
var skipTakeWithVariable2 = blogs
.OrderBy(b => b.Id).Where(d => d.Name.Length > example2.Length).ToList();

这样就很明了了为什么通过变量达到查询计划重用的目的。

总结

关于EntityFramework Core虽然目前设计的性能非常好,但是有些东西等我们去用时还得多加验证,看其背后的本质是怎样的,才能不会心生疑窦,到底该怎样用,如何用,心中要有定数才是,一点一滴的细小优化不注意最终将导致大意失荆州。接下来博主会在三个方向不定时更新博客,第一个是SQL Server性能优化系列,第二个是ASP.NET Core MVC/WebAPi,第三个则是EntityFramework Core原理解析,敬请期待。

EntityFramework Core不得不注意的性能优化意外收获,你会用错?的更多相关文章

  1. EntityFramework之原始查询及性能优化(六)

    前言 在EF中我们可以通过Linq来操作实体类,但是有些时候我们必须通过原始sql语句或者存储过程来进行查询数据库,所以我们可以通过EF Code First来实现,但是SQL语句和存储过程无法进行映 ...

  2. EntityFramework之原始查询及性能优化

    之前做海信项目,数据量自交大,为了提高查询效率用的 https://www.cnblogs.com/CreateMyself/p/4746258.html

  3. 第 10 章 MySQL Server 性能优化

    前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的 ...

  4. MySql(十):MySQL性能调优——MySQL Server性能优化

    本章主要通过针对MySQL Server( mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的参数优 ...

  5. MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化

    第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...

  6. Spark 3.x Spark Core详解 & 性能优化

    Spark Core 1. 概述 Spark 是一种基于内存的快速.通用.可扩展的大数据分析计算引擎 1.1 Hadoop vs Spark 上面流程对应Hadoop的处理流程,下面对应着Spark的 ...

  7. EntityFramework之异步、事务及性能优化(九)

    前言 本文开始前我将循序渐进先了解下实现EF中的异步,并将重点主要是放在EF中的事务以及性能优化上,希望通过此文能够帮助到你. 异步 既然是异步我们就得知道我们知道在什么情况下需要使用异步编程,当等待 ...

  8. Instruments性能优化-Core Animation

    简书地址:http://www.jianshu.com/users/6cb2622d5eac/latest_articles 当App发展到一定的规模.性能优化就成为不可缺少的一点.可是非常多人,又对 ...

  9. EntityFramework Core 3多次Include导致查询性能低之解决方案

    前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...

随机推荐

  1. git的安装和环境配置过程(学习笔记)

    1.安装git 官网下载:https://github.com(目前官网好像找不到了,但是妙味的视频里面是在官网下载的)https://git-for-windows.github.io/ (廖雪峰老 ...

  2. 从项目经理的角度看.net的MVC中Razor语法真的很垃圾.

    我们知道,Razor语法中我们可以直接使用@if(){}等代码段,这使得.net程序员在写模版时更容易了. 对比如下: 语法名称 Razor 语法 Web Forms 等效语法 代码块(服务端) @{ ...

  3. 磁盘工作原理与IO性能分析

    最近,在研究如何优化产品设备的磁盘IO性能,需要深入研究磁盘及文件系统原理和工作机制,下面简要总结下关于磁盘方面的东西,下篇文章再分享文件系统的. 机械磁盘结构: 无论哪种机械硬盘,都主要由盘片.磁头 ...

  4. 【新建项目&使用viewPager】实现一个Android电子书阅读APP

    本章结尾处已放出应用DEMO,已经实现所有本文及后续文章所述全部功能,大家可以先下载下来玩玩看,欢迎在本文下方评论,小方很需要鼓励支持!!! 新建一个项目 呼-我们即将步入安卓开发之旅了,首先要新建一 ...

  5. Asp.Net 常用工具类之加密——对称加密DES算法(2)

    又到周末,下午博客园看了两篇文章,关于老跳和老赵的程序员生涯,不禁感叹漫漫程序路,何去何从兮! 转眼毕业的第三个年头,去过苏州,跑过上海,从一开始的凌云壮志,去年背起行囊默默回到了长沙准备买房,也想有 ...

  6. 使用multer搭建一个图片接收服务器

    为了测试图片上传插件的上传功能是否好用,最近尝试搭建了一个接收图片的服务器,因为图片上传的编码格式是form-data,所以我选择使用express+multer,实现过程中发现有几个需要注意的地方, ...

  7. ERP顾问工作中应该注意哪些工作是不该做的

    1.不要轻易对客户说“不“ 当客户提出一个问题顾问要判断一下,是否属于顾问实施的问题,如果属于顾问实施范畴,而自己又不清楚,这时应把问题纪录下来,和客户解释清楚,回去请教资深顾问给与回答,如果该问题不 ...

  8. Phpcms 详情页显示所属栏目的同级栏目

    Phpcms详情页是不显示所属栏目的同级栏目的,如果按下面的方式 {loop subcat($parentid) $v} <li{if $v[catid]==$catid} class=&quo ...

  9. Java面试02|Java集合

    关于Java中并发集合有: (1)CouncurrentHashMap (2)CopyOnWriteArrayList (3)LinkedBlockingQueue (4)ArrayBlockingQ ...

  10. Java面试03|并发及锁

    1.synchronized与Lock的区别 使用synchronized这个关键字实现的同步块有一些缺点: (1)锁只有一种类型 (2)线程得到锁或者阻塞 (3)Lock是在Java语言层面基于CA ...