ado.net與EF的關係之EF生成SQL的效率研究

来源:http://www.cnblogs.com/DKnight/archive/2016/06/23/5611853.html
-Advertisement-
Play Games

EF和SqlHelper 簡單三層 EF生成sql,再調用ado.net訪問資料庫,最後使結果對象具體化. 之前的SqlHelper 簡單三層的寫法,拼接sql語句字元串,再調用ado.net訪問資料庫,最後也是把結果轉換為對象. 明顯的區別:sql語句的產生,EF是SQL查詢命令和 LINQ 查詢 ...


EF和SqlHelper 簡單三層

  •  EF生成sql,再調用ado.net訪問資料庫,最後使結果對象具體化.
  •  之前的SqlHelper 簡單三層的寫法,拼接sql語句字元串,再調用ado.net訪問資料庫,最後也是把結果轉換為對象.

明顯的區別:sql語句的產生,EF是SQL查詢命令和 LINQ 查詢生成,SqlHelper簡單三層是程式員直接拼接sql語句.
那麼,一直談EF性能,不得不說EF產生sql的速度.

回顧上篇文章提到的 EntityFramework性能之預生成視圖 ,裡面有張 查詢執行的各個階段 圖解.
各個階段如下:

  1. 載入元數據,中等成本,在每個應用程式域中一次.
  2. 打開資料庫連接.(使用ado.net也免不了.)
  3. 生成視圖,成本雖高,卻在每個應用程式域中指執行一次.(上篇文章折騰了半天,最終覺得EF6.1.3和.net 4.5已經優化過了,不必在意這個預生成視圖.)
  4. 準備查詢,中等成本.每個唯一查詢一次。註釋:因為實體 SQL查詢命令和 LINQ 查詢現已緩存,所以,以後執行相同查詢所需的時間較少。 您仍可以使用已編譯的 LINQ 查詢來降低後續執行中的這一開銷,編譯的查詢比自動緩存的 LINQ 查詢效率更高。
  5. 執行查詢,低成本,每個查詢一次。註釋:使用 ADO.NET 數據提供程式對數據源執行命令的成本。 因為大多數數據源緩存查詢計劃,所以,以後執行相同查詢所需的時間可能較少。
  6. 載入和驗證類型,跟蹤,使對象具體化

建立項目

(EF中還是用之前的PhoneBookModel.edmx,熟悉的名字.)
這次用asp.net mvc.在Home控制器下,有兩個方法.

public ActionResult PreHot()
        {
            var db = new PhoneBookEntities();
            db.ContactInGroup.ToList();
            return View();
        }
PreHot
public ActionResult Test()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();

            using (var db = new PhoneBookEntities())
            {
                var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
                var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
                ci.ContactName += "!";
                gi.GroupName += "!";

                using (var tx = db.Database.BeginTransaction())
                {
                    try
                    {
                        db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=209");
                        db.SaveChanges();
                        tx.Commit();//此語句不要漏了,否則監控結果會是釋放了事務,而不是提交了事務!
                    }
                    catch (Exception)
                    {
                        tx.Rollback();
                    }
                }
            }
            sw.Stop();
            ViewBag.time = sw.ElapsedMilliseconds;//在視圖裡顯示花費的時間
            return View();
        }
Test

註意:之前文章提過,怎麼監控sql語句.而在監控記錄里,會給出執行sql語句的時間.對於Test方法中EF生成的sql語句,
記錄顯示:    執行-- 已在 1 毫秒內完成,結果為: SqlDataReader. 

測試開始:

  • a操作.清理解決方案,生成,先訪問/home/index,再直接訪問 /Home/Test,用時1250毫秒,再次訪問 /Home/Test ,時間顯示2-15毫秒.(/home/index,裡面沒任何代碼,僅用來啟動網站)
  • b操作.清理解決方案,生成,先訪問/home/index,之後訪問/Home/PreHot,再訪問 /Home/Test,顯示時間 250毫秒,再次訪問 /Home/Test 時間顯示2-15毫秒.

對於這個結果,我的解釋是:
a操作,訪問/Home/Test,執行Test()方法,而此時,要走 查詢執行階段的1,2,3,4,5,6,對比之前的 查詢執行的各個階段,就明白為什麼會用時1250毫秒這麼久(相比資料庫執行查詢只需要1毫秒.);

再次訪問/Home/Test時, 查詢執行階段的1和3不用走(應用程式域中一次),4也不走(每個唯一查詢一次[Test()方法里的查詢執行過一次了,不唯一了,查詢已自動緩存]),5執行查詢(使用了緩存查詢計劃,使以後執行相同查詢所需的時間可能較少),再走6.所以用時大幅度降低到2-15毫秒(顯示時間大多在5毫秒左右,給個小公式:5毫秒=執行sql語句用時1毫秒+EF產生sql語句用時4毫秒).

b操作,訪問/Home/PreHot,先讓 查詢執行階段的1和3走了一次.再訪問 /Home/Test,走4,5,6,顯示時間 250毫秒(對比a操作首次訪問 /Home/Test,少了對性能影響較大的1和3階段).

再次訪問 /Home/Test 時間顯示2-15毫秒(同a操作).

也就是說,經過EF的初次使用,再加上 實體 SQL查詢命令和 LINQ 查詢 被自動緩存,滿足這兩個條件後,生成sql語句速度極快(應該不會大於5毫秒).
如果一個網站使用的是EF,稍微有點訪問量,EF生成sql語句的速度已不是問題.(同樣的測試Test()方法,在控制台里,時間一直是350毫秒左右...?) 

生成sql語句的速度已不是問題,那麼接下來就是生成sql語句的質量.之前的博文,希望大家看過.
如果EF生成sql的質量夠好,EF的效率就不是問題,我感覺其效率會無限接近原生的ado.net.
下篇,會拿 SqlHelper操作Ado.net跟使用EF做個對比.

如果,你初學EF,有一個表ContactInfo,含100W行數據, 而你寫了一行這樣的代碼:
var res= db.ContactInfo.ToList().Skip(5).Take(5);
發現速度極慢,你就想EF真垃圾,我不使用EF,毫秒中搞定.再也不看EF啦.那就是你的損失了.自已用的不好,卻在怪EF不行.

Ado.net和EF的關係,就好比c跟java和c#的關係.
理論上說,c的效率要比java和c#高.但java和c#還是被廣泛使用.
但是,同樣的功能,同樣用c#去寫,有的人寫的程式會高效.因為他在用c#語言中,會避開耗性能的拆箱裝箱,會更高效地去使用StringBuilder去拼接比較複雜的字元等.
c#語言本身的好的.但是程式員能不能高效地使用它又是另外一回事了.

同樣的,EF也是好的,就看你對它的瞭解有多深入了.
會Ado.net,知道怎麼寫sql更優,明白怎麼監控EF產生的sql語句,就會對瓶頸進行調優,就能把EF變成自己的利器.這也就是我先看EF產生的sql的原因.
如果什麼都不知道,就用EF一頓瞎寫,就好比用webForm一頓拖伺服器控制項, 把網址拖慢了,把人拖的腦殘了(只會拖控制項,換個jsp就懵逼了...估計控制項拖的連請求,處理,響應都弄不明白.)
(博客園 dudu 關於EF的文章,我大多看了,不過版本是EF4.根據 dudu博文,博客園也是用了EF這個利器的.)

您認為EF如何呢? 


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

-Advertisement-
Play Games
更多相關文章
  • zip命令的基本用法是: zip [參數] [打包後的文件名] [打包的目錄路徑] linux zip命令參數列表: -a 將文件轉成ASCII模式 -F 嘗試修複損壞的壓縮文件 -h 顯示幫助界面 -m 將文件壓縮之後,刪除源文件 -n 特定字元串 不壓縮具有特定字尾字元串的文件 -o 將壓縮文件 ...
  • 1、啟動網卡 2、SSH鏈接 ifconfig 查看IP後SSH終端連接3、更新源 最小化安裝是沒有wget工具的,必須先安裝再修改源 備份原系統更新源 進入yum.repos.d目錄 下載網易鏡像源或者搜狐鏡像源 網易搜狐的源可能有問題。 參考http://blog.csdn.net/ichson ...
  • #卸載mysql /etc/init.d/mysqld stop &> /dev/null killall mysqld &> /dev/null sudo rm -rf /mengdi/server/mysql &> /dev/null sudo rm -rf /mengdi/server/mys ...
  • nmon 下載:http://pan.baidu.com/s/1jICoSpo 放到linux下可以直接運行。 nmon 工具可以幫助在一個屏幕上顯示所有重要的性能優化信息,並動態地對其進行更新。 nmon 工具可以為 AIX 和 Linux 性能專家提供監視和分析性能數據的功能,其中包括: CPU ...
  • 三個文件夾,第一個是放置前端部分,第二個是各種支持的類文件,第三個是單元測試文件。 Core文件類庫 放置的是與資料庫做交互的文件,以及一些第三方類庫,還有與資料庫連接的文件 1.Lasy.Validator是一個基於Attribute驗證器,我覺得這種驗證方式在挺便捷的,具體可以在這裡查看到htt ...
  • 這些對象都是用來保存信息的,包括用戶信息,傳遞值的信息,全局信息等等。下麵主要說一下他們之間的區別: 1.Application對象 Application用於保存所有用戶的公共的數據信息,如果使用Application對象,一個需要考慮的問題是任何寫操作都要在Application_OnStart ...
  • 引言 HTTP 是一個屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分散式超媒體信息系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和 擴展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的規範化工作正在進行之中,而且HTTP-NG(Next Genera ...
  • 背水一戰 Windows 10 之 綁定: 與 Element 綁定, 與 Indexer 綁定, TargetNullValue - 當綁定數據為 null 時顯示的值, FallbackValue - 當綁定失敗時顯示的值 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...