利用Cache緩存數據DataTable數據提高大數據量訪問性能(轉貼)

Cache 即高速緩存 ,我想很多人對他的第一印象一定像我一樣,感覺他一定能提高系統得性能和運行速度。的確。Net推出cache的初衷確實是這樣的。那麼cache是如何提高系統性能與運行速度呢?是不是在任何情況下用cache都能提高性能?是不是cache用的越多就越好呢?我在近期開發的項目中有所體會,寫下來當作總結也希望能跟大家一起探討探討,有錯誤的地方希望大家批評指正。

  1. Cache 是如何工作的。

Cache 是分配在服務器上的一個公共的內存片。
所謂公共指的cache只要一創建是任何一個客戶端瀏覽器都可以通過後臺代碼訪問到它,它面向的是所有用戶,相對而言session也是服務器上的一段內存,但他面向的是單個用戶。它是服務器的一段內存塊,也就是說每個cache一經創建就佔用了服務器資源的。所以從這點來說我們就可以說:並不是cache越多越好。 cache 是有時間限制的,超過了服務器設定的過期時間,它就會被服務器回收。 cache 可以存放任何對象

  2. Cache 如何創建以及如何銷燬。

創建cache
在。Net環境下通過Cache.Insert(string key,object o)方法創建。其中key 代表cache的ID,o代表存到cache裏的對象。 銷燬cache.
通過方法Cache.Remove(string key)其中key 代表cache的 ID。 調用cache.
Cache支持裝箱/拆箱操作。如你可以把一個DataSet對象ds通過Cache.Insert("dsCache",ds)的方式存到Cache中,可以通過拆箱操作 DataSet ds = (DataSet)Cache["dsCache"]來訪問它。

  3. 什麼時候用cache.
  Cache 一般用於數據較固定,用的較頻繁的地方。例如可以把進銷存系統中可以把產品信息存入cache,在用戶調用產品信息時通過調用cache即可,這樣從很大程度上減少了用戶與數據庫的交互,提高了系統的性能。反之,cache不適合用在數據變動快,使用範圍很窄的地方。例如把一個具體採購單存入 cache中。

  4. cache 調用注意事項。
  Cache是有時間限制的。超過了服務器設置的過期時間,就會被服務器回收。當cache被回收後對應的內存塊就會被清空,再次通過cache[“cachekey”]訪問對象時返回的就是null值。所以以下這種調用就會出現異常:

DataSet ds = (DataSet)Cache[“cacheds”];
DataRow dr = ds.Table[0].Row[0]; //出錯,ds爲null值,不存在表0。

正確的寫法應該是:

DataSet ds
If(Cache["cacheds"] != null) {
ds = (DataSet)Cache[“cacheds”];
}
Else {
ds= GetDsFromDataBase();
}
DataRow dr = ds.Table[0].Row[0];



在數據量不大的情況下,程序怎麼寫基本上性能差別不大,但是當我們面對數以萬計的數據的時候,我想性能就是個不得不考慮的問題了,每寫一個方法,每填充一筆數據都要考慮到性能問題,否則服務器將承擔巨大的執行開銷,如果服務器性能不好可能立即就死在那裏了,所以在大數據量頻繁訪問的頁面上,我們就必須考慮如何提高頁面的性能了,本文將提供一種用cache提高訪問性能的方法來解決此問題,在很大程度上提高頁面加載數據的性能。本文列舉的是論壇版塊中帖子列表頁面加載數據的實例。
正文:
每個版塊帖子列表信息都會對應一個cache的名字,比如,我們可以按照規律設成
1 #region -- CacheName Setting --
2 boardCacheName = "Board" + boardID.ToString();
3 #endregion
4 
這裏我們同樣是採取數據集填充DataTable的方法創建數據的。不過,因爲我們有了cache,所以,我們在第一次加載完數據後,會把數據壓到cache中,然後每次填充DataTable前進行判斷,如果cache爲空時才加載,如果不爲空,則不加載。
 1private DataTable BuildDataTable()
 2{
 3     // 數據緩存 機制
 4       if(Cache[boardCacheName] != null)
 5       {
 6              // Create DataTable From Cache
 7              DataTable dt = (DataTable)Cache[boardCacheName];
 8              return dt;
 9       }

10       else
11       {
12              // Create DataTable From DataBase
13              DataTable dt = new DataTable();
14 
15              -- Create DataTable --#region -- Create DataTable --
16              dt.Columns.Add("TopicID", System.Type.GetType("System.Int32"));
17              //省去N個類似字段的添加
18              dt.Columns.Add("CoolState", System.Type.GetType("System.Int32"));
19              DataColumn[] keys = new DataColumn[1];
20              keys[0= dt.Columns[0];
21              dt.PrimaryKey = keys;
22              #endregion

23 
24              -- Add DataRow --#region -- Add DataRow --
25              BBSTopicCollection btc = new BBSTopicCollection();
26              btc.BoardID = this.boardID;
27              btc.TopicState = 1;
28              if(!btc.GetInfo())
29              {
30                     return dt;
31              }

32              for(int i=0;i<btc.Count;i++)
33              {
34                     DataRow dr = dt.NewRow();
35                     // 帖ID
36                     dr["TopicID"= btc[i].ID;
37                     //省去N個類似字段的數據賦值
38                     // Cool State
39                     dr["CoolState"= btc[i].CoolState;
40                     dt.Rows.Add(dr);
41              }

42              #endregion

43 
44              // Push DataTable To Cache
45              Cache[boardCacheName] = dt;
46              return dt;
47       }

48}

49
 
上面的代碼完成了數據填充過程,但更重要的是對數據進行管理,比如,我們改變一條住處的某些狀態位來實現一些功能,比如,我們把貼子加成“酷貼”,這個時候就要對cache進行操作,特別注意一下,我們在上面的代碼中還特別設置topicID這一列作爲表的主值鍵,這樣我們才能很快的定位到要管理的數據信息,方法如下。
 1 #region -- Cache Management --
 2 if(Cache["Board" + this.boardID.ToString()] != null)
 3 {
 4        DataTable dt = (DataTable)Cache["Board" + this.boardID.ToString()];
 5        DataRow dr = dt.Rows.Find(topicID);
 6        if(dr != null)
 7        {
 8               dr["CoolState"= 1;
 9               dr.AcceptChanges();
10               dt.AcceptChanges();
11        }
12 }
13 #endregion
14 
 
一點說明:其中的topicID是通過某種途徑傳過來的你想操作的信息的唯一標識字段,AcceptChanges方法更新保存相應對象數據自上一次更新以來所有的更改,另外對cache進行操作後,記得要重新綁定數據,另外也要同時更新數據庫中的,本文認爲讀者具備對數據庫數據進行操作的能力,便不作贅述。
那麼我們如何來刪除數據記錄呢?我們是不是可以直接在找到dr的那一行下面,用個
dr.Delete()來把數據刪除就完事了呢?答案是否,這樣操作會出現問題,經測試對cache的添加和更新操作會立即生效,但刪除某條記錄的動作不會立即起作用,這樣就會導致數據操作異步性,這是不可以的,同時1.1版本比1.0版本要稍微好一些,但還是解決不了異步性的問題,所以我們是不是必須把cache幹掉,重新填充一下呢,如果你願意這樣做,自然也無可厚非,我這裏提供另外一個思路供參考。
我們的解決方案是,在創建表格的時候多加一個刪除標誌位,比如DeleteState,當初從數據庫中加載出來的時候都一律爲1,然後經過刪除操作以後,將這條信息的刪除標誌位置0(不要忘記同時操作數據庫中的數據),然後綁定的時候對DataView進行過濾,dv.RowFilter = "DeleteState==1",便可以模擬出刪除效果了。
數據經過這樣的處理之後,訪問性能會數以百倍的提高,數據只在cache失效後纔會重新加載,用戶對數據的訪問都是對cache的操作,而且cache是服務器變量,對所有用戶共享,這樣,如果同時有一百個用戶訪問,也都是對同一個cache進行一百次訪問,而程序訪問cache是非常快的,如果不使用cache,那麼,我們就要去跑一百次數據庫操作,性能極差,尤其是當海量用戶對海量數據進行訪問的時候,服務器可謂苦不堪言,所以用cache來緩解負荷是相當必要且相對優良的一種方案,只是辛苦了那位在cache失效後第一次訪問頁面的那個用戶,不過這種犧牲換來別人的高性能也是值得的嘛。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章