EF Core 使用編譯查詢提高性能

来源:https://www.cnblogs.com/tdfblog/archive/2018/01/15/ef-core-compilequery.html
-Advertisement-
Play Games

今天,我將向您展示這些EF Core中一個很酷的功能,通過使用顯式編譯的查詢,提高查詢性能。 不過在介紹具體內容之前,需要說明一點,EF Core已經對錶達式的編譯使用了緩存;當您的代碼需要重用以前執行的查詢時,EF Core將使用哈希查找並從緩存中返回已編譯的查詢。 關於這一點,您可以查閱gith ...


今天,我將向您展示這些EF Core中一個很酷的功能,通過使用顯式編譯的查詢,提高查詢性能。

不過在介紹具體內容之前,需要說明一點,EF Core已經對錶達式的編譯使用了緩存;當您的代碼需要重用以前執行的查詢時,EF Core將使用哈希查找並從緩存中返回已編譯的查詢。

關於這一點,您可以查閱github上面的代碼QueryCompiler.cs

不過,您可能希望直接對查詢進行編譯,跳過哈希的計算和緩存查找。我們可以通過在EF靜態類中下麵兩個方法來實現:

這些方法允許您定義一個已編譯的查詢,然後通過調用一個委托調用它。

如果您對錶達式的哈希計算感興趣,可以看一看它的實現,非常複雜,ExpressionEqualityComparer.cs

為了避免因為資料庫查詢產生測試結果的差異,我們這裡使用記憶體資料庫,它開銷更小,同時也可以避免資料庫優化執行計劃以及緩存所帶來的問題。

實體定義以前資料庫DbContext

定義實體

在這我們定義一個Category實體類型,非常簡單,只有兩個屬性。

    public class Category
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

資料庫DbContext

FillCategories方法中,將記憶體資料庫中增加三條記錄。

    public class TestDbContext : DbContext
    {
        public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
        {
        }

        public DbSet<Category> Categories { get; set; }

        public void FillCategories()
        {
            var foodCategory = new Category {
                Id = Guid.NewGuid(),
                Name = "Food"
            };

            Categories.AddRange(foodCategory, new Category {
                Id = Guid.NewGuid(),
                Name = "Drinks"
            }, new Category {
                Id = Guid.NewGuid(),
                Name = "Clothing"
            }, new Category {
                Id = Guid.NewGuid(),
                Name = "Electronis"
            });


            SaveChanges(true);
        }
    }

測試代碼

    public class CompileQueryTest
    {
        private   Func<TestDbContext, Guid, Category> _getCategory =
            EF.CompileQuery((TestDbContext context, Guid id) => context.Categories.FirstOrDefault(c => c.Id == id));

        private readonly TestDbContext _dbContext;

        public CompileQueryTest()
        {
            var options = new DbContextOptionsBuilder<TestDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
            var context = new TestDbContext(options);

            context.FillCategories();

            _dbContext = context;
        }

        private readonly Guid _queryId = Guid.NewGuid();

        [Benchmark]
        public void CompiledQuery()
        {
            _ = _getCategory(_dbContext, _queryId);
        }


        [Benchmark]
        public void UnCompiledQuery()
        {

            _ = _dbContext.Categories.FirstOrDefault(c => c.Id == _queryId);

        }
    }

為了更加接近測試結果,我們在構造函數中創建TestDbContext對象以及填充資料庫。

測試結果

我們使用Benchmark.Net進行基準測試,測試結果如下:

Method Mean Error StdDev
CompiledQuery 10.59 us 0.0580 us 0.0543 us
UnCompiledQuery 79.55 us 0.7860 us 0.7353 us

經過編譯的查詢比未編譯過的查詢存在接近8倍的差距。如果您對這個功能感興趣,不防自己測試一下。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Using mac os python3.6 to connect ssl will occur urllib.error.URLError. It requires a post-install step, which installs the certifi package of certifi ...
  • 一、Listener監聽器 Javaweb開發中的監聽器,是用於監聽web常見對象 HttpServletRequest HttpSession ServletContext 監聽它們的創建與銷毀、屬性變化 以及session綁定javaBean 1、監聽機制 事件 就是一個事情 事件源 產生這個事 ...
  • 才開始《Spring源碼深度解析》就碰到了問題,按照書上的步驟從github上下載了源碼,然後導入項目後,缺少spring-cglib-repack-3.2.5.jar和spring-objenesis-repack-2.6.jar這兩個jar包。 網上很多解決辦法都是從spring-core中解壓 ...
  • 最近老是聽說協程很火,心也很癢癢想知道這到底是個什麼東西,今天就花功夫看了看Boost庫里的Coroutine。誰不曾想Boost庫這麼難搞,等到要寫代碼時編譯出錯了。其實這也不能怪Boost,大部分Boost庫都是以頭文件的形式提供的,直接include就可以了。但是Coroutine這個東西用了 ...
  • 背水一戰 Windows 10 之 文件系統: 獲取文件夾的屬性, 獲取文件夾的縮略圖 ...
  • AdminController中添加引用: Index添加[Authorize]許可權要求: StartUp.cs中添加引用: StartUp.cs ConfigureServices中添加常量: 添加中間件: 此時,訪問Admin頁面,自動跳轉至Account/Login?ReturnUrl=%2F ...
  • 打斷點打不出火花,這個問題糾結了我兩天時間,查問了度娘許久,網上各種說法。我一直認為是我的環境設置問題,但就是沒辦法找到問題所在。 我想起哪天部署WEB的時候,點了一下“代碼優化”,於是還原了代碼優化,結果問題解決了。 哈哈 這樣就能打出火花了 ...
  • 1. 單一職責原則(Single Responsibility Principle) 每一個類應該專註於做一件事情。 每一個職責都是變化的一個軸線,如果一個類有一個以上的職責,這些職責就耦合在了一起。這會導致脆弱的設計。當一個職責發生變化時,可能會影響其它的職責。另外,多個職責耦合在一起,會影響復用 ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...