EntityFramework Core不得不注意的性能优化意外收获,你会用错?
来源:互联网 发布:淘宝银龙裁决多少钱 编辑:程序博客网 时间:2024/06/08 16:47
前言
这两天在着实研究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(1)
.Take(1)
.ToList();
var example2 = blogs
.Skip(10)
.Take(10)
.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 = 1;
var example1 = blogs .Skip(count) .Take(count) .ToList(); count = 10;
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 > 1).ToList();
var skipTakeWithInt2 = blogs .OrderBy(b => b.Id).Where(d => d.Name.Length > 10).ToList();
看出什么没有,对于上述两条查询则是对应进行了两次SQL查询,这下意识到了其中玄机了吧,下面我们将上述再改造一下:
var ef = new EFCoreContext();
var blogs = ef.Blogs;
var length = 1;
var skipTakeWithVariable1 = blogs .OrderBy(b => b.Id).Where(d => d.Name.Length > length).ToList(); length = 10;
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 = 1;
var example1 = new ExampleClass1() { Length = length };
var skipTakeWithVariable1 = blogs .OrderBy(b => b.Id).Where(d => d.Name.Length > example1.Length).ToList(); length = 10;
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原理解析,敬请期待。
原文地址:http://www.cnblogs.com/CreateMyself/p/6665423.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
- EntityFramework Core不得不注意的性能优化意外收获,你会用错?
- EntityFrameWork 性能优化
- 意外的收获
- 意外的收获
- 意外的收获
- 意外的小收获
- 意外的收获access
- 网站优化不得不注意的问题
- 关于checkbox你不得不注意的事情
- Java性能优化,不得不付诸实践的JVM
- 你不得不知道的 MySQL 优化原理
- 你不得不知道的 MySQL 优化原理
- 整理屋子的意外收获
- 新公司的意外收获
- 足球课的意外收获
- 意外收获
- 意外收获
- 性能优化的一些注意
- NuGet社区使用体验调查
- 安卓学习笔记---让WebView不可滑动(上下左右)
- 微服务网关Ocelot
- [认证授权] 2.OAuth2授权(续) &amp; JSON Web Token
- 83
- EntityFramework Core不得不注意的性能优化意外收获,你会用错?
- 在ASP.NET Core中使用Apworks快速开发数据服务
- 自制scratch小游戏
- 我为什么鼓励工程师写blog
- NuGet社区使用体验调查
- .NET Core开源组件:后台任务利器之Hangfire
- 微软宣布12月15日关闭开源软件托管平台CodePlex
- Visual Studio 2017通过SSH支持Git
- Xamarin的Kimono以及Google的Guetzli和Draco