最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

.net 中的SqlConnection連接池機制詳解

 更新時間:2013年04月23日 12:16:09   作者:  
.net 中通過 SqlConnection 連接 sql server,我們會發(fā)現(xiàn)第一次連接時總是很耗時,但后面連接就很快,這個其實和SqlConnection 的連接池機制有關(guān)

正確的理解這個連接池機制,有助于我們編寫高效的數(shù)據(jù)庫應用程序。

很多人認為 SqlConnection 的連接是不耗時的,理由是循環(huán)執(zhí)行 SqlConnection.Open 得到的平均時間幾乎為0,但每次首次open 時,耗時又往往達到幾個毫秒到幾秒不等,這又是為什么呢?

首先我們看一下 MSDN 上的權(quán)威文檔上是怎么說的

Connecting to a database server typically consists of several time-consuming steps. A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on.

以上摘自 http://msdn.microsoft.com/en-us/library/8xx3tyca%28VS.80%29.aspx

也就是說物理連接建立時,需要做和服務器握手,解析連接字符串,授權(quán),約束的檢查等等操作,而物理連接建立后,這些操作就不會去做了。這些操作是需要一定的時間的。所以很多人喜歡用一個靜態(tài)對象存儲 SqlConnection 來始終保持物理連接,但采用靜態(tài)對象時,多線程訪問會帶來一些問題,實際上,我們完全不需要這么做,因為 SqlConnection 默認打開了連接池功能,當程序 執(zhí)行  SqlConnection.Close 后,物理連接并不會被立即釋放,所以這才出現(xiàn)當循環(huán)執(zhí)行 Open操作時,執(zhí)行時間幾乎為0.

下面我們先看一下不打開連接池時,循環(huán)執(zhí)行 SqlConnection.Open 的耗時

復制代碼 代碼如下:

        public static void OpenWithoutPooling()       
 {           
 string connectionString =  "Data Source=192.168.10.2; Initial Catalog=News; Integrated Security=True;Pooling=False;";
 Stopwatch sw = new Stopwatch();          
 sw.Start();           
 using (SqlConnection conn =  new SqlConnection(connectionString))           
 {               
 conn.Open();           
 }           
 sw.Stop();           
 Console.WriteLine("Without Pooling, first connection elapsed {0} ms", sw.ElapsedMilliseconds); 

 sw.Reset();         
 sw.Start();         
 for (int i = 0; i < 100; i++)    
 {              
 using (SqlConnection conn = new SqlConnection(connectionString))  
 {                 
 conn.Open();            
 }         
 }      
 sw.Stop();        
 Console.WriteLine("Without Pooling, average connection elapsed {0} ms", sw.ElapsedMilliseconds / 100); 
 }

復制代碼 代碼如下:

.csharpcode { BACKGROUND-COLOR: #ffffff; FONT-FAMILY: consolas, "Courier New", courier, monospace; COLOR: black; FONT-SIZE: small }
.csharpcode PRE { BACKGROUND-COLOR: #ffffff; FONT-FAMILY: consolas, "Courier New", courier, monospace; COLOR: black; FONT-SIZE: small }
.csharpcode PRE { MARGIN: 0em }
.csharpcode .rem { COLOR: #008000 }
.csharpcode .kwrd { COLOR: #0000ff }
.csharpcode .str { COLOR: #006080 }
.csharpcode .op { COLOR: #0000c0 }
.csharpcode.preproc { COLOR: #cc6633 }
.csharpcode .asp { BACKGROUND-COLOR: #ffff00 }
.csharpcode .html { COLOR: #800000 }
.csharpcode .attr { COLOR: #ff0000 }
.csharpcode .alt { BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; WIDTH: 100% }
.csharpcode .lnum { COLOR: #606060 }

SqlConnection 默認是打開連接池的,如果要強制關(guān)閉,我們需要在連接字符串中加入 Pooling=False

調(diào)用程序如下:

復制代碼 代碼如下:

                Test.SqlConnectionTest.OpenWithoutPooling(); 
  Console.WriteLine("Waiting for 10s");         
  System.Threading.Thread.Sleep(10 * 1000);      
  Test.SqlConnectionTest.OpenWithoutPooling();       
  Console.WriteLine("Waiting for 600s");           
  System.Threading.Thread.Sleep(600 * 1000);            
  Test.SqlConnectionTest.OpenWithoutPooling();

下面是測試結(jié)果

復制代碼 代碼如下:

Without Pooling, first connection elapsed 13 ms
Without Pooling, average connection elapsed 5 ms
Wating for 10s
Without Pooling, first connection elapsed 6 ms
Without Pooling, average connection elapsed 4 ms
Wating for 600s
Without Pooling, first connection elapsed 7 ms
Without Pooling, average connection elapsed 4 ms

從這個測試結(jié)果看,關(guān)閉連接池后,平均每次連接大概要耗時4個毫秒左右,這個就是建立物理連接的平均耗時。

下面再看默認情況下的測試代碼

復制代碼 代碼如下:

        public static void OpenWithPooling() 
 {        
 string connectionString =  "Data Source=192.168.10.2; Initial Catalog=News; Integrated Security=True;";
 Stopwatch sw = new Stopwatch();   
 sw.Start();       
 using (SqlConnection conn =  new SqlConnection(connectionString))    
 {             
 conn.Open();   
 }        
 sw.Stop();      
 Console.WriteLine("With Pooling, first connection elapsed {0} ms", sw.ElapsedMilliseconds);
 sw.Reset();   
 sw.Start();    
 for (int i = 0; i < 100; i++)   
 {            
 using (SqlConnection conn = new SqlConnection(connectionString))   
 {                 
 conn.Open();        
 }          
 }        
 sw.Stop();       
 Console.WriteLine("With Pooling, average connection elapsed {0} ms", sw.ElapsedMilliseconds / 100); 
 }

調(diào)用代碼

復制代碼 代碼如下:

                Test.SqlConnectionTest.OpenWithPooling();    
  Console.WriteLine("Waiting for 10s");        
  System.Threading.Thread.Sleep(10 * 1000);      
  Test.SqlConnectionTest.OpenWithPooling();      
  Console.WriteLine("Waiting for 600s");    
  System.Threading.Thread.Sleep(600 * 1000); 
  Test.SqlConnectionTest.OpenWithPooling();

測試結(jié)果

With Pooling, first connection elapsed 119 ms
With Pooling, average connection elapsed 0 ms
Waiting for 10s
With Pooling, first connection elapsed 0 ms
With Pooling, average connection elapsed 0 ms
Waiting for 600s
With Pooling, first connection elapsed 6 ms
With Pooling, average connection elapsed 0 ms


這個測試結(jié)果看,第一次耗時是119ms,這是因為我在測試代碼中,首先運行的是這個測試過程,119 ms 是程序第一次啟動時的首次連接耗時,這個耗時可能不光包括連接數(shù)據(jù)庫的時間,還有 ado.net 自己初始化的用時,所以這個用時可以不管。10秒以后在執(zhí)行這個測試過程,首次執(zhí)行的時間變成了0ms,這說明連接池機制發(fā)生了作用,SqlConnection Close 后,物理連接并沒有被關(guān)閉,所以10秒后再執(zhí)行,連接幾乎沒有用時間。

但我們發(fā)現(xiàn)一個有趣的現(xiàn)象,10分鐘后,首次連接時間變成了6ms,這個和前面不打開連接池的測試用時幾乎一樣,也就是說10分鐘后,物理連接被關(guān)閉了,又重新打開了一個物理連接。這個現(xiàn)象是因為連接池有個超時時間,默認情況下應該在5-10分鐘之間,如果在此期間沒有任何的連接操作,物理連接就會被關(guān)閉。那么我們有沒有辦法始終保持物理連接呢?方法是有的。

連接池設置中有一個最小連接池大小,默認為0,我們把它設置為大于0的值就可以保持若干物理連接始終不釋放了??创a

復制代碼 代碼如下:

       public static void OpenWithPooling(int minPoolSize)
       {        
       string connectionString = string.Format("Data Source=192.168.10.2; Initial Catalog=News; Integrated Security=True;Min Pool Size={0}",minPoolSize); 
       Stopwatch sw = new Stopwatch();      
       sw.Start();     
       using (SqlConnection conn =   new SqlConnection(connectionString)) 
       {              
       conn.Open();    
       }       
       sw.Stop();   
       Console.WriteLine("With Pooling Min Pool Size={0}, first connection elapsed {1} ms",minPoolSize, sw.ElapsedMilliseconds);
       sw.Reset();         
       sw.Start();      
       for (int i = 0; i < 100; i++)   
       {               
       using (SqlConnection conn = new SqlConnection(connectionString))   
       {                  
 conn.Open();       
 }    
 }      
 sw.Stop();    
 Console.WriteLine("With Pooling Min Pool Size={0}, average connection elapsed {1} ms",minPoolSize, sw.ElapsedMilliseconds / 100); 
 }

其實只要在連接字符串中加入一個 Min Pool Size=n 就可以了。

調(diào)用代碼

復制代碼 代碼如下:

               Test.SqlConnectionTest.OpenWithPooling(1);    
        Console.WriteLine("Waiting for 10s");     
        System.Threading.Thread.Sleep(10 * 1000); 
        Test.SqlConnectionTest.OpenWithPooling(1);       
        Console.WriteLine("Waiting for 600s");            
        System.Threading.Thread.Sleep(600 * 1000);     
        Test.SqlConnectionTest.OpenWithPooling(1);

With Pooling Min Pool Size=1, first connection elapsed 5 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms
Waiting for 10s
With Pooling Min Pool Size=1, first connection elapsed 0 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms
Waiting for 600s
With Pooling Min Pool Size=1, first connection elapsed 0 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms


我們可以看到當 Min Pool Size = 1  時,除了首次連接用時5ms以外,即便過了10分鐘,用時還是0ms,物理連接沒有被關(guān)閉。

 

多線程調(diào)用問題
多線程調(diào)用我也做了測試,這里不貼代碼了,我大概講一下結(jié)果。如果是多線程訪問 SqlConnection ,注意是通過 new SqlConnection 方式訪問,

那么這里有兩個問題,如果后一個線程在前一個線程 Close 前調(diào)用了Open操作,那么 Ado.net 不可能復用一個物理連接,它將為第二個線程分配一個新的物理連接。如果后一個線程 Open  時,前一個線程已經(jīng) Close 了,則新的線程使用前一個線程的物理連接。也就是說,如果同時有n個線程連接數(shù)據(jù)庫,最多情況下會創(chuàng)建n條物理連接,最少情況下為1條。如果創(chuàng)建n條物理連接,則用時理論上等于 n * t / cpu , n 為線程數(shù),t 為每次創(chuàng)建物理連接的用時,前面測試的結(jié)果大概是5-10ms左右,cpu 為當前機器的CPU數(shù)量。另外網(wǎng)絡,服務器的負荷也影響這個用時。為了保證在大并發(fā)時,盡量少的創(chuàng)建新的物理連接,我們可以適當把 Min Pool Size 調(diào)大一些,但也不要太大,因為單個機器TCP鏈路的數(shù)量是有限的,詳見我另外一篇文章 Windows 下單機最大TCP連接數(shù)

連接字符串中關(guān)于 連接池方面的參數(shù)

見下面鏈接 SqlConnection.ConnectionString Property

 

IIS 回收應用程序池對連接池的影響
在做 ASP.NET 程序時,我們會發(fā)現(xiàn),如果網(wǎng)站20分鐘不訪問,再次訪問就會比較慢,這是因為IIS默認的 idle timeout 是20分鐘,如果在20分鐘內(nèi)沒有一個訪問,IIS 將回收應用程序池,回收應用程序池的結(jié)果就相當于應用程序被重啟,所有原來的全局變量,session, 物理連接都將清空?;厥諔贸绦虺睾笫状卧L問,相當于前面我們看到的程序啟動后第一次訪問數(shù)據(jù)庫,連接的建立時間將比較長。所以如果網(wǎng)站在某些時段訪問量很少的話,需要考慮 idle timeout 是否設置合理。

相關(guān)文章

  • ASP.NET中為DataGrid添加合計字段

    ASP.NET中為DataGrid添加合計字段

    ASP.NET中為DataGrid添加合計字段...
    2006-09-09
  • ASP.NET中Response.BufferOutput屬性的使用技巧

    ASP.NET中Response.BufferOutput屬性的使用技巧

    這篇文章介紹了ASP.NET中Response.BufferOutput屬性的使用技巧,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 把Dapper 換成 SqlSugar ORM類的方法詳解

    把Dapper 換成 SqlSugar ORM類的方法詳解

    這篇文章主要介紹了把Dapper 換成 SqlSugar ORM類的方法詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • ASP.NET使用正則表達式屏蔽垃圾信息

    ASP.NET使用正則表達式屏蔽垃圾信息

    找資料,看看如何實現(xiàn)使用正則表達式屏蔽垃圾信息,找來找去找出來的都不怎么好,有不詳細的,有代碼缺失的。最后還是找到了微軟,先摘過來,大概思路已經(jīng)有了,只需把下面微軟給的樣例代碼修改一下即可,具體能不能行還不知道,先睡一覺,起來再慢慢研究。
    2008-09-09
  • 一文搞懂MemoryCache 清除全部緩存的方法

    一文搞懂MemoryCache 清除全部緩存的方法

    這篇文章主要介紹了MemoryCache 清除全部緩存的方法,本文給大家介紹兩個方法,每種方法通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • C#多線程Singleton(單件)模式模板

    C#多線程Singleton(單件)模式模板

    下面是一個C#多線程單件模式的代碼模板。把T換成你自己的類型就可以使用了。其精妙之處就在于用lock語句鎖定資源來避免多線程同時走入if語句去創(chuàng)建多個對象
    2012-02-02
  • vs2010顯示代碼行數(shù)的方法

    vs2010顯示代碼行數(shù)的方法

    這篇文章主要為大家詳細介紹了如何在vs2010中顯示代碼的行數(shù),僅要三步實現(xiàn)代碼行數(shù)顯示,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • MVC使用Memcache+Cookie解決分布式系統(tǒng)共享登錄狀態(tài)學習筆記6

    MVC使用Memcache+Cookie解決分布式系統(tǒng)共享登錄狀態(tài)學習筆記6

    這篇文章主要介紹了MVC使用Memcache+Cookie解決分布式系統(tǒng)共享登錄狀態(tài)學習筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Asp.net GridView使用大全(分頁實現(xiàn))

    Asp.net GridView使用大全(分頁實現(xiàn))

    關(guān)于GridView的使用涉及很多,網(wǎng)絡上零零散散的有一些,為了讓自己使用方便,也為了大家能很好的學習與工作,我把網(wǎng)絡上的GridView使用方法收集了一些
    2013-04-04
  • .NET性能優(yōu)化ValueStringBuilder拼接字符串使用實例

    .NET性能優(yōu)化ValueStringBuilder拼接字符串使用實例

    這篇文章主要為大家介紹了.NET性能優(yōu)化ValueStringBuilder拼接字符串的使用實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06

最新評論

东台市| 富川| 蛟河市| 香港 | 石嘴山市| 抚州市| 濉溪县| 赫章县| 雅安市| 扎兰屯市| 南投县| 枞阳县| 紫金县| 红桥区| 甘南县| 凤阳县| 景德镇市| 保山市| 长沙县| 潼南县| 景宁| 沙雅县| 礼泉县| 庆城县| 巴南区| 宁蒗| 广宗县| 精河县| 洛浦县| 盐池县| 綦江县| 肥东县| 合肥市| 昌平区| 小金县| 婺源县| 丹阳市| 金昌市| 犍为县| 武宁县| 迁西县|