PDF.NET開發框架性能剖析

 

前倆天發佈了 關於PDF.NET開發框架對Mysql Sqlite PostgreSQL數據庫分頁支持的我的見解 ,說明了本人對框架的一些介紹和見解。今天咱們一塊兒思考一些問題。html

 

 

1.裝箱與拆箱sql

EntityBase.cs數據庫

 1 private object[] values;
 2 /// <summary>
 3 /// 屬性值列表
 4 /// </summary>
 5 public virtual object[] PropertyValues
 6 {
 7     get
 8     {
 9         if (values == null)
10         {
11             values = new object[PropertyNames.Length];
12         }
13         return values;
14     }
15     protected internal set { values = value; }
16 }

每一個實體類對象,通常狀況下至關於表中的一行數據。把屬性裏封裝的字段放在數組中,字段有值類型(tinyint int double...) 引用類型,爲了知足各類類型只能由object類型出廠,這樣會致使值類型頻繁進行拆箱(引用類型到值類型--get)/裝箱(值類型到引用類型--set)操做.這在必定程度上,對性能形成了損耗。數組

 

2.for與foreach緩存

CommonDB.cs框架

 1 if (parameters != null)
 2     for (int i = 0; i < parameters.Length; i++)
 3         if (parameters[i] != null)
 4         {
 5             if (commandType != CommandType.StoredProcedure)
 6             {
 7                 //IDataParameter para = (IDataParameter)((ICloneable)parameters[i]).Clone();
 8                 IDataParameter para = parameters[i];
 9                 if (para.Value == null)
10                     para.Value = DBNull.Value;
11                 cmd.Parameters.Add(para);
12             }
13             else
14             {
15                 //爲存儲過程帶回返回值
16                 cmd.Parameters.Add(parameters[i]);
17             }
18         }

使用for循環,加數組的索引器使用(每調用一次,就循環一次,能夠反編譯查看),會形成數組的重複遍歷。話很少說,看哥代碼,你懂得!ide

 1 if (parameters != null)
 2 {
 3     foreach (IDataParameter para in parameters)
 4     {
 5         if (para != null)
 6         {
 7             if (commandType != CommandType.StoredProcedure)
 8             {
 9                 if (para.Value == null)
10                     para.Value = DBNull.Value;
11                 cmd.Parameters.Add(para);
12             }
13             else
14             {
15                 //爲存儲過程帶回返回值
16                 cmd.Parameters.Add(para);
17             }
18         }
19     }
20 }

 

3.雙重鎖定 double check性能

SqlCache.csui

 1 /// <summary>
 2 /// 增長一項到緩存中
 3 /// </summary>
 4 /// <param name="key"></param>
 5 /// <param name="item"></param>
 6 /// <returns></returns>
 7 public static bool AddToCache(string key,SqlInfo item)
 8 {
 9     SqlInfo Value = GetFromCache(key);
10     if (Value != null)
11         return false;
12     lock (sync_obj)
13     {
14         DictSqlCache.Add(key, item);
15     }
16     return true;
17 }

第一個if確實能減小鎖的影響,提示性能。 lock裏須要作判斷的...看代碼spa

 1 /// <summary>
 2 /// 增長一項到緩存中
 3 /// </summary>
 4 /// <param name="key"></param>
 5 /// <param name="item"></param>
 6 /// <returns></returns>
 7 public static bool AddToCache(string key, SqlInfo item)
 8 {
 9     if (!DictSqlCache.ContainsKey(key))//在lock前判斷,有助於提高性能
10     {
11         lock (sync_obj)//假設2個線程同時執行到這,若是lock裏不作判斷會出問題
12         {
13             if (!DictSqlCache.ContainsKey(key))
14             {
15                 DictSqlCache.Add(key, item);
16                 return true;
17             }
18         }
19     }
20     return false;
21 }

 

 

4.分頁

SqlPage.cs

 1 /// <summary>
 2 /// 根據主鍵的高效快速分頁之 升序分頁
 3 /// </summary>
 4 /// <param name="pageNum">頁碼,從1開始</param>
 5 /// <param name="pageSize">頁大小,大於1</param>
 6 /// <param name="filedList">字段列表</param>
 7 /// <param name="tableName">表名稱</param>
 8 /// <param name="PKName">主鍵名稱</param>
 9 /// <param name="conditon">查詢條件</param>
10 /// <returns>返回指定頁碼的快速分頁SQL語句</returns>
11 public static string GetAscPageSQLbyPrimaryKey(int pageNum, int pageSize, string filedList, string tableName, string PKName, string conditon)
12 {
13     if (conditon == null || conditon == "")
14         conditon = "1=1";
15     if (pageNum == 1)
16     {
17         string sqlTemplage = "Select top @pageSize @filedList from @table1 where  @conditon order by @PKName desc ";
18         return sqlTemplage
19             .Replace("@pageSize", pageSize.ToString())
20             .Replace("@filedList", filedList)
21             .Replace("@table1", tableName)
22             .Replace("@conditon", conditon)
23             .Replace("@PKName", PKName);
24     }
25     else
26     {
27         //@topNum= ((頁碼-1)*頁大小)
28         string sqlTemplage = @"
29 select top @pageSize @filedList
30 from @table1
31 where @conditon And @PKName>
32     (select max (@PKName) from
33     (select top @topNum @PKName from @table1 where @conditon order by @PKName asc) as T
34     )    
35 order by @PKName asc
36 ";
37         int topNum = (pageNum - 1) * pageSize;
38 
39         return sqlTemplage.Replace("@topNum", topNum.ToString())
40             .Replace("@pageSize", pageSize.ToString())
41             .Replace("@filedList", filedList)
42             .Replace("@table1", tableName)
43             .Replace("@conditon", conditon)
44             .Replace("@PKName", PKName);
45 
46     }
47 }
View Code

 

 首先,要把字符串對象構造爲StringBuilder對象,用StringBuilder對象的Replace方法,這些細節和上篇也提到了,不少人會認爲這是廢話,好吧......我不說廢話了,進入重點。

 

看了不少分頁代碼,有not in的,rownum僞列的,limit的。但若是隻根據一列進行查詢,主鍵列或其餘值類型的列都可,這種分頁無疑是性能最高的。我的很欣賞做者的代碼。

可是,我想提一個問題,

假如tableName參數傳入的是一個viewName(視圖名稱),

而這個視圖是有10張同結構的表,或不一樣結構的表抽取意義相同的列的數據  union而成。

這個視圖數據量百萬級數據量。這麼寫能禁得住考驗嗎?

那麼該如何改進呢?

相信clever的你已經懂了,若還沒想通,那就經歷3重境界吧:

   昨夜西風凋碧樹,獨上高樓,望盡天涯路。

   衣帶漸寬終不悔,爲伊消得人憔悴。

   而後是驀然回首...........

相關文章
相關標籤/搜索