前言

这两天在着实研究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. 如何修改Window系统下PATH路径以及win8下masm32V11

    如何修改Window系统下PATH路径   //其实这个都是临时性的, 退出dos窗口就没有用了,只是做个笔记罢了   C:\Users\Administrator>    set path=E ...

  2. DEV下拉框LookUpEdit使用技巧

    1,首先设置LookUpEdit要绑定的列,并配置隐藏列 2,设置下拉框是否显示表头,底部 3.设置下拉框宽度 4.设置显示的列与值列 5.设置初始值 6,绑定数据 7,取值  

  3. Web Service ,WCF以及Web API的对比

    Web Service 1.基于SOAP和XML形式的返回数据. 2.只支出HTTP协议. 3.只能运行在IIS环境下. 4.不是开源的,但可以由任何支持xml的客户端下使用. WCF 1.基于SOA ...

  4. RancherOS 学习笔记(一)

    今天只是简单了解下rancheros,以及尝试安装了下. 这是官网文档:http://docs.rancher.com/os/ 这是官网Github地址:https://github.com/ranc ...

  5. 第十六篇 基于Bootstarp 仿京东多条件筛选插件的开发(展示上)

    这几天学习Bootstrap,本来是两年前的用的东西,现在又重新拾起来,又有很多重新的认识,看了Bootstrap的样式偏多,插件现在还没有学习到几个,也有写几个插件自己用的想法.正好工作上也会用到, ...

  6. Javascript中好用更改时间的方法

    <script type="text/javascript"> //格式化时间格式的字符串 String.prototype.myTimes = function () ...

  7. php 与redis 结合 使用predis

    分为2步骤 1.下载predis 2.使用predis,让php与redis进行通信 <?php require('autoload.php'); $redis = new Predis\Cli ...

  8. java线程学习(一)

    1.简介 java基础知识部分线程创建的三种方式.线程执行的样例. 代码地址:http://git.oschina.net/blue_phantom/javaj 包位置:package com.blu ...

  9. 入坑系列之HAProxy负载均衡

    在大型系统设计中用代理在负载均衡是最常见的一种方式,而相对靠谱的解决方案中Nginx.HAProxy.LVS.F5在各大场中用得比较普遍,各有各的优势和使用场景,由于本次要使用到TCP,因此Nginx ...

  10. Android中的WebView实战详解(二)

    四.如何用WebView下载软件? 四.如何用WebView下载软件? public class MainActivity extends AppCompatActivity { private We ...