EntityFramework Core不得不注意的性能优化意外收获,你会用错?
前言
这两天在着实研究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不得不注意的性能优化意外收获,你会用错?的更多相关文章
- EntityFramework之原始查询及性能优化(六)
前言 在EF中我们可以通过Linq来操作实体类,但是有些时候我们必须通过原始sql语句或者存储过程来进行查询数据库,所以我们可以通过EF Code First来实现,但是SQL语句和存储过程无法进行映 ...
- EntityFramework之原始查询及性能优化
之前做海信项目,数据量自交大,为了提高查询效率用的 https://www.cnblogs.com/CreateMyself/p/4746258.html
- 第 10 章 MySQL Server 性能优化
前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的 ...
- MySql(十):MySQL性能调优——MySQL Server性能优化
本章主要通过针对MySQL Server( mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化,但不包括mysqld之外的比如存储引擎相关的参数优 ...
- MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化
第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...
- Spark 3.x Spark Core详解 & 性能优化
Spark Core 1. 概述 Spark 是一种基于内存的快速.通用.可扩展的大数据分析计算引擎 1.1 Hadoop vs Spark 上面流程对应Hadoop的处理流程,下面对应着Spark的 ...
- EntityFramework之异步、事务及性能优化(九)
前言 本文开始前我将循序渐进先了解下实现EF中的异步,并将重点主要是放在EF中的事务以及性能优化上,希望通过此文能够帮助到你. 异步 既然是异步我们就得知道我们知道在什么情况下需要使用异步编程,当等待 ...
- Instruments性能优化-Core Animation
简书地址:http://www.jianshu.com/users/6cb2622d5eac/latest_articles 当App发展到一定的规模.性能优化就成为不可缺少的一点.可是非常多人,又对 ...
- EntityFramework Core 3多次Include导致查询性能低之解决方案
前言 上述我们简单讲解了几个小问题,这节我们再来看看如标题EF Core中多次Include导致出现性能的问题,废话少说,直接开门见山. EntityFramework Core 3多次Include ...
随机推荐
- Angular企业级开发(7)-MVC之控制器
1.MVC中的控制器 AngularJS的控制器主要为了把模型和视图连接在一起.大多数业务逻辑操作都会放在视图对应的控制器中.当然如果我们能够把业务逻辑放到后端的REST服务中,就可以开发轻量级Ang ...
- GCD(关于容斥原理)
Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD( ...
- HL-340编译驱动
make -C /lib/modules/3.4.39/build SUBDIRS=/home/linaro/Desktop/ch341_drv modulesmake: *** /lib/modul ...
- 新注册第一帖----------------------乱码新手自学.net 之Linq 入门篇
作为一个业余开发,断断续续学.net/c#也有不少日子了, 学习过程中,不断忘了学,学了忘,这让我很苦恼. 以前学习过程中,我总是在笔记本中记录下来知识要点,这么久下来,笔记本都写了四五本了. 然而, ...
- Winfrom 提示消息框公共类
1.Winfrom项目经常会使用到消息提示,一般都使用MessageBox.Show方法,但是像错误提示,询问提示,警告提示写起来就有点复杂了,并且后面几种提示都带有图标,但是MessageBox.S ...
- 【CNMP系列】PHP配置和调优
上一节我们说到PHP5.6.30在CentOS7.0下的整个安装过程,http://www.cnblogs.com/riverdubu/p/6428226.html 今天我来和大家讲解一下PHP-FP ...
- 微软MSBI商业智能视频
第一讲:BI介质安装.BI基础知识讲解.BI方法论讲解.项目讲解 1.BI基础知识讲解.BI方法论实施2.微软BI的介绍(数据仓库介绍.SSIS介绍.SSAS介绍.SS ...
- 电器ERP行业案例——环力科技
环力科技ERP案例 企业简介 [规模] 环力公司始建于1992年,是一家专业生产电子压力控制器.水泵压力控制器.气泵压力控制器.电泵浮球控制器.全自动水泵及其它配套产品研究.开发.生产.销售为一体的专 ...
- Python 3中字符串可以被改变吗?
Python 3中字符串可以被改变吗? 字符串有改变这个方法的:replace,比如: a = 'lkjhgfdsa' a.replace(') '123kjhgfdsa' #返回结果 从上面这个例子 ...
- ACM 序号互换
序号互换 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 Dr.Kong设计了一个聪明的机器人卡多,卡多会对电子表格中的单元格坐标快速计算出来.单元格的行坐标是由数字 ...