.NET TIPS

[ASP.NET]データセットをキャッシングするには?

山田 祥寛
2004/08/27

 アプリケーションにはさまざまなデータが混在している。例えば、メニュー情報や組織情報のように、ほとんど更新される可能性がない基本データ。在庫情報や取引情報のように、日々更新されるトランザクション・データ。これら異なる性質のデータに対して一様に動的な読み込みを行うのは、パフォーマンス的にも好ましくないことは明らかだ。

 ほとんど変更される可能性がない情報であるならば、1度目のアクセスでデータベースなどから読み込んだ内容をメモリ上に保持しておけばよい。そのうえで、2度目以降のアクセスでは、メモリ上に保持されたデータを利用するのだ。これによって、データベースやファイル・システムへの無駄なアクセスを減らすことができ、結果として、アプリケーション全体のパフォーマンス向上が望める。

 本稿では、このようなデータ・キャッシングの手法について紹介することにしよう。以下は、書籍情報(books.xml)を読み込み、その内容をDataGridコントロールに展開する、ごく基本的なサンプル・プログラムだ。ただし、初回アクセス時にbooks.xmlをメモリ上にキャッシングすることで、2回目以降のアクセスではファイル・システムへのアクセスを抑制することができる。具体的な記述例は以下のとおりだ。

<%@ Page ContentType="text/html" Language="C#" %>
<%@ Import Namespace="System.Data" %>
<script runat="Server">
void Page_Load(Object sender, EventArgs e) {
  DataSet objDs=new DataSet();
  // キャッシュ"books"が存在する場合はキャッシュの内容を、
  // 存在しない場合はbooks.xmlをデータセットに読み込み、
  // 同時にキャッシュにセットする
  if (Cache.Get("Books") == null) {
    objDs.ReadXml(Server.MapPath("books.xml"));
    Cache.Insert("Books", objDs);
  } else {
    objDs = (DataSet)Cache.Get("Books");
  }
  objGrd.DataSource = objDs;
  DataBind();
}
</script>
<html>
<head>
<title>キャッシュの活用</title>
</head>
<body>
<form runat="Server">
  <asp:DataGrid id="objGrd" runat="Server" AutoGenerateColumns="False">
    <HeaderStyle BackColor="#BB2255" ForeColor="white" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />
    <Columns>
      <asp:BoundColumn DataField="isbn" HeaderText="ISBNコード" />
      <asp:BoundColumn DataField="title" HeaderText="書名" />
      <asp:BoundColumn DataField="price" HeaderText="価格" />
      <asp:BoundColumn DataField="publish" HeaderText="出版社" />
      <asp:BoundColumn DataField="published" HeaderText="配本日" />
    </Columns>
  </asp:DataGrid>
</form>
</body>
</html>
データ・キャッシングを行うサンプル・プログラム:C#版(cache_cs.aspx)
 
<%@ Page ContentType="text/html" Language="VB" %>
<%@ Import Namespace="System.Data" %>
<script runat="Server">
Sub Page_Load(sender As Object, e As EventArgs)
  Dim objDs As New DataSet()
  ' キャッシュ"Books"が存在する場合はキャッシュの内容を、
  ' 存在しない場合はbooks.xmlをデータセットに読み込み、
  '同時にキャッシュにセットする
  If IsDbNull(Cache.Get("Books")) Or IsNothing(Cache.Get("Books")) Then
    objDs.ReadXml(Server.MapPath("books.xml"))
    Cache.Insert("Books", objDs)
  Else
    objDs = Cache.Get("Books")
  End If
  objGrd.DataSource = objDs
  DataBind()
End Sub
</script>
<html>
<head>
<title>キャッシュの活用</title>
</head>
<body>
<form runat="Server">
  <asp:DataGrid id="objGrd" runat="Server" AutoGenerateColumns="False">
    <HeaderStyle BackColor="#BB2255" ForeColor="white" />
    <ItemStyle BackColor="#FFeeEE" />
    <AlternatingItemStyle BackColor="#FFDDDD" />
    <Columns>
      <asp:BoundColumn DataField="isbn" HeaderText="ISBNコード" />
      <asp:BoundColumn DataField="title" HeaderText="書名" />
      <asp:BoundColumn DataField="price" HeaderText="価格" />
      <asp:BoundColumn DataField="publish" HeaderText="出版社" />
      <asp:BoundColumn DataField="published" HeaderText="配本日" />
    </Columns>
  </asp:DataGrid>
</form>
</body>
</html>
データ・キャッシングを行うサンプル・プログラム:VB.NET版(cache_vb.aspx)

 ここで行っているデータ・キャッシングの仕組みそのものは、ごく単純だ。あらかじめ用意されているCacheオブジェクトを利用するだけで、指定されたキーに対して任意のオブジェクトを関連付ける(キャッシュに挿入する)ことができる。

Cache.Insert("Books", objDs)

 逆に、キャッシュ内のデータを取得するには、次のようにする。

objDs = Cache.Get("Books")

 もしも指定したキャッシュを明示的に破棄したい場合には、Removeメソッドで以下のように記述すればよい。

Cache.Remove("books")

 それではさっそく、該当のWebフォーム・ページにアクセスして、キャッシュが有効となっている様子を見てみよう。まずこのタイミングでbooks.xmlの内容がデータセットとしてCacheオブジェクトに格納される。

初回アクセス時のサンプル・プログラムの実行結果

 次いで、books.xmlのデータをテキスト・エディタなどから変更したうえで、もう一度、ページにアクセスする。すると、books.xmlの変更内容がブラウザ上では反映されておらず、メモリ上のキャッシュ・データが使われていることが確認できるはずだ。

2回目以降のアクセス時のサンプル・プログラムの結果
books.xmlをエディタなどで変更後に再度アクセスしても、メモリ上のキャッシュが使われているため、サンプル・プログラムの実行結果にはbooks.xmlの変更内容は反映されていない。

 このように、データ・キャッシングは手軽に実現できるパフォーマンス改善のアプローチの1つだ。しかし、いくら便利だからといって、何から何までデータ・キャッシングの対象にしてしまうことは当然好ましくない。

 例えば、頻繁に更新が行われるデータをキャッシュしてしまうと、実際のデータ内容とアプリケーション上の表示に食い違いが起こるリスクが生じてしまうし、これを回避するために短いスパンでキャッシュをリフレッシュ(更新)するのでは、キャッシングの効果は得にくい。また、メモリ・リソースを浪費する分、むしろアプリケーションにとっては悪影響を及ぼす可能性もあるだろう。リソースを考慮した場合、あまりに巨大なデータをキャッシュしておくことも好ましくない。メモリを消費することによるデメリットと、パフォーマンス改善のメリットは環境によっても異なるので、一概にこれだといえる指標はないが、キャッシュと引き換えに失われるものもあるのだということは、常に意識しておくべきだろう。

 以上のような観点から、一般的には以下のようなデータがキャッシングに適しているといえる。

  • 更新頻度が少ない(あるいは原則的に更新がない)データ
  • 容量がさほど大きくないデータ
  • アクセス頻度が多いデータ

 キャッシングの是非を判断する際の参考にしていただきたい。End of Article

カテゴリ:Webフォーム 処理対象:キャッシング
使用キーワード:Cacheオブジェクト
使用ライブラリ:Cacheクラス(System.Web.Caching名前空間)
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]データベース更新のタイミングでキャッシュを破棄するには?
[ASP.NET]リクエスト・パラメータごとにページをキャッシングするには?
[ASP.NET]キャッシュ破棄のタイミングを指定するには?
[ASP.NET]Webフォーム・ページの一部分を断片的にキャッシングするには?
WPF:DataGridやListViewなどに表示しているデータを別スレッドから変更するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間