日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

EntityFramework Core不得不注意的性能优化意外收获,你会用错?

發布時間:2023/12/4 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(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不得不注意的性能优化意外收获,你会用错?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。