Silverlight をインストールするには、ここをクリックします*
Japan変更|すべてのMicrosoft のサイト|サインイン
MSDN
|MSDN ライブラリ|デベロッパー センター|ダウンロード情報|開発ツール製品|コミュニティ|ご意見・ご要望|サイトマップ
MSDN Home > 連載コラム > Nothin' but ASP.NET > ASP.NET キャッシュ

ASP.NET キャッシュ

Rob Howard
Microsoft Corporation

April 26, 2001
日本語版最終更新日 2001年6月18日

今月のコラムでは、ASP.NET のもう 1 つの新機能であるキャッシュについて見ていく つもりです。Beta 1 には、2 つの異なる機能、ページ出力キャッシュと新しい Cache オブジェクトがあります。ASP.NET の Beta 2 では、さらにいくつかキャッシュ機能が導入 される予定です。これらの機能については、Beta 2 のリリース後にこのコラムで説明するつ もりです。

キャッシュ

キャッシュとは、通常生成にコストがかかるデータを再利用するために、頻繁に使用 するデータを格納するプロセスです。一般的には、データベースなどのほかの場所からデータ を取得するよりも、メモリからデータを取得する方がはるかに効率的なので、キャッシュされ るデータはメモリに格納されます。

ASP.NET には、キャッシュをサポートする機能がいくつか含まれています。たとえば、 任意のデータを格納するキャッシュ API や頻繁に要求されるページを格納するために使 用される出力キャッシュがあります。

ここで、簡単な例を説明しましょう。

電子商取引サイトで使用されるカタログが、1 週間に 1 度だけ変更されるとします。 顧客が商品を購入できるように、そのカタログのフロント エンド インターフェイスを提供する ASP.NET Web アプリケーションを構築します。顧客が単にカタログを参照している場合、 システムは (ほとんどの場合に) バックエンド データベース サーバーに対してネットワーク呼 び出しを行います。また、データベース サーバーが、結合クエリなどでデータを演算し、結 果を返すこともあります。

カタログや、その他の種類のデータベースから一般的に要求されるデータでは、この種の 構成がかなり一般的です。ただし、上記の例では設計を改善できます。データベース内 のデータが 1 週間に 1 度だけしか変更されないことを認識しており、データの取得に関連 して次のようないくつかのパフォーマンス コストが存在することもわかっています。

  1. データベースへの要求を行う ASP.NET コードを実行します。

  2. データベース サーバーと通信するために、Web サーバーがネットワークを使 用します。

  3. クエリをコンパイルおよび実行 (または単にストアド プロシージャを実行) す るためにデータベース サーバーで作業を行います。

キャッシュを使用すると、上記の作業の多くの部分を取り除き、アプリケーションのパ フォーマンスとスケーラビリティを向上できます。結果をキャッシュし、それらを静的 (各要 求が動的なのに対して) に利用することにより、パフォーマンスを向上できます。さらに、各 要求をサービスするために使用するリソースがより少なくなるので、スケーラビリティが増加 します。

ASP.NET の Beta 1 では、キャッシュ API と、キャッシュ API を使用するページ出力 キャッシュを導入しました。これら 2 つの機能をもう少し詳しく説明しましょう。

キャッシュ API

頻繁に要求されるデータをメモリに格納することは、ASP 開発者にとって新しいことで はありません。この問題を解決する次の 2 種類のオブジェクトがありました。

  • Session オブジェクト

  • Application オブジェクト

Session オブジェクトは、複数の要求にまたがるデータをユーザーごとに格納す るために使用されます。changes for Session in ASP.NET には、 ASP.NET での Session オブジェクトの変更点がいくつか説明されていますが、これらの変更 点の大部分は、アプリケーション レベルの変更で、Session オブジェクトの使用方法 には影響しません。つまり、Session オブジェクトは依然として単なるキー/値のペア です。

また、Application オブジェクトも、ASP から ASP.NET に移行されており、関数 (キー/値のペア) ではまったく変更されていません。たとえば、ASP または ASP.NET のどちらで も、次のコードを記述できます。

Application("SomeInterestingData") = "Example data"
Response.Write(Application("SomeInterestingData")

Session オブジェクトでも、同じ意味合いで使用されます。単純にキーに名前を付 けます。この場合は、SomeInterestingData を使用しました。そしてそれに値を 代入します。この場合は "Example data" を代入しました。

ASP.NET は、別のキー/値のペア オブジェクト、Cache オブジェクトを導入します。 Cache オブジェクトは、キー/値のペアを単純に格納することに以外にも、一時的な データを格納するために特別に設計された別の機能を追加します。

  • 依存関係Cache オブジェクトに追加されるキーは、 そのキーを Cache オブジェクトから強制的に削除できる依存関係を設定できます。 サポートされる依存関係には、キー、ファイル、および時刻があります。

  • 自動的な期限切れ—依存関係を持たない Cache オブジェクトに追加された使用中のアイテムは、アイテムが使用中の場合に自動的に期限切 れになります。

  • コールバックのサポート—アイテムが Cache オブジェクトから削除 されるときに呼び出されるコード パスが追加されます。これにより、Cache オブジェクト を更新するか、アイテムを削除しない機会を提供します。

Cache を使用するアプリケーションのコードを記述する場合に、次のことを考慮す る必要があります。

Cache を使用する前に、アイテムが Cache に存在するかどうかを常に確認します。

Cache では、依存関係に基づいたアイテムまたは使用中のアイテムの有効期限が切れる ので、アイテムが Cache オブジェクト内に存在しない場合、必要なアイテムを作成また は取得するコードを常に記述する必要があります。

たとえば、データが設定された DataSet を返す関数を記述する場合、次のようになります。

Private Function LoadDataSet() As DataSet
  Dim sqlConnection As SQLConnection
  Dim sqlAdapater As SQLDataSetCommand
  Dim datasetProducts As New DataSet()
  Dim sqlDSN As String
  Dim sqlSelect As String

  ' 接続文字列と Select ステートメント
  sqlDSN = "server=localhost;uid=sa;pwd=;database=grocertogo"
  sqlSelect = "Select * From Products"

  ' 接続
  sqlConnection = new SQLConnection(sqlDSN)
  sqlAdapater = new SQLDataSetCommand(sqlSelect, sqlConnection)

  ' 製品テーブルを作成して、データセットを設定します
  sqlAdapter1.FillDataSet(datasetProducts, "products")

  Return products
End Function

Cache を利用するコードを簡単に記述できます。結果の DataSet が まだ Cache に存在しない場合のみ、次のように LoadDataSet() を実行します。

Public Function GetProductData() As DataSet
  If (IsNothing(Cache("ProductData")) Then
    Cache("ProductData") = LoadDataSet()

  Return Cache("ProductData")
End Function

ただし、実際には Application を使用することとすべてが異なるわけでは ありません。本質的には、これとまったく同じことを実現することができます。興味深いの は、依存関係を設定するときです。

Cache の依存関係

依存関係を使用して、ファイルへの変更、その他の Cache キーへの変更、 またはある特定の時刻に基づいて、Cache 内の特定のアイテムを無効にでき ます。これらの依存関係を個別に見ていきましょう。

ファイルに基づく依存関係

ファイルに基づく依存関係は、ディスク上のファイルが変更されると、特定の Cache アイテムを無効にします。たとえば、ProductData をデータベースから読み込む代わりに、 XML ファイルからそれを読み込んでいるとしましょう。この場合読み込みは、次のようになります。

Dim dom As XmlDocument()
dom.Load(Server.MapPath("product.xml")
Cache("ProductData") = dom

product.xml が変更されると、Cache 内のデータは明らかに無効に なります。product.xml が要求しているアプリケーションと同じディレクトリ に存在すると仮定すると、次のようになります。

Dim dependency as new CacheDependency(Server.MapPath("product.xml"))
Cache.Insert("ProductData", dom, dependency)

上記のコード例では、CacheDependency クラスのインスタンス、依存関係を作成し、 product.xml ファイルへのパスに渡しています。その後、Cache の Insert() メソッ ドを使用して、データの取得先のファイルに依存する ProductData キーを作成します。

キーに基づく依存関係

キーに基づく依存関係は、別の Cache アイテムが変更されるときに、特定の Cache アイテムを無効にします。たとえば、アプリケーションが ProductDataSalesData、および MarketingData など、複数の DataSet を Cache に追加し、SalesData および MarketingData が有効な ProductData に依存している場合を考えます。この場合、 キーに基づく依存関係を使用して、ProductData が変更されるときに、 SalesData および MarketingData を無効にできます。SalesData および MarketingData の Cache エントリ を作成するときに、この依存関係を設定します。

Dim dependency (1) As String
dependencyKey(0) = "ProductData"
Dim productDataDependency As new CacheDependency(nothing, dependencyKey)

Cache.Insert("SalesData", LoadDataSet("Sales"), productDataDependency)

上記のコード例では、Insert() メソッドを使って、SalesData という名前の新しい Cache エントリを作成します。このとき、Cache キーに ProductData という名前を付けて、productDataDependency という CacheDependency クラスのインスタンスに渡します。これで、ProductData が変更されるときは必ず、 SalesData が Cache から削除されます。

時間に基づく依存関係

時間に基づく依存関係は、単純に定義された時点でアイテムの有効期限が切れる ようにします。繰り返しになりますが、Cache の Insert() メソッドを使って、この 依存関係を作成します。時間に基づく依存関係には 2 つの選択肢があります。

  • 絶対時刻—絶対時刻を設定します。たとえば、Cache エン トリに現在の時刻 + 10 分を有効期限として設定します。

  • 経過時間—Cache 内のアイテムで、要求ごとに有効期限 を再設定します。

経過時間 有効期限オプションを使用して、最長 10 分間 ProductData DataSet を Cache に保存できます。ProductData への要求が 10 分 以内に行われる限り、データはさらに 10 分間有効になります。

' 10 分間の時間間隔
Dim span As New TimeSpan(0,10,0)
Cache.Insert("ProductData", LoadDataSet(), nothing, nothing, span)

ここまで、比較的簡単にキャッシュ API を説明してきましたが、それを使用することがいかに 簡単かを理解していただけたことを願います。実際表面には現れませんが、ASP.NET はキャッシュ API およびその時間に基づく有効期限の考え方を使用して、ページ出力キャッシュをサポート します。今後のコラムで、キャッシュ API についての詳しく取り上げていくつもりです。

ページ出力キャッシュ

ページ出力キャッシュは、指定されたページのコンテンツ全体を Cache に格納できる ようにする ASP.NET の機能です。上記の例では、キャッシュ API を使って、Cache に DataSets を格納しました。単純に DataSet を格納するのではなく、(DataSet の結果を表 示する) ページ全体をキャッシュできるとしたらどうなるでしょうか ? ここでの利点は、要求ごと に ASP.NET ページを動的に実行するのではなく、ページをメモリから静的に供給することで す。この結果、パフォーマンスが飛躍的に向上するでしょう !

ページ出力キャッシュを使った作業用に、低レベルと高レベルの両方の API があります。 この記事の残りの部分で、高レベルの API のみを説明しますが、今後のコラム (Beta 2 のリ リース後) で低レベルの API について説明するつもりです。

高レベルの API は、定期的にページから結果をキャッシュするように ASP.NET に指示す る Page ディレクティブで構成されます。

<%@ OutputCache Duration="10" %>

ASP.NET ページの先頭に追加された上記のディレクティブは、単純に 10 秒ごとに ページの結果をキャッシュすることを ASP.NET に指示します。10 秒後に、そのページは 再実行されます。以下に、このディレクティブを使用する例を示します。

<%@ OutputCache Duration="10" %>
<Script runat="server">
  Public Sub Page_Load()
    span1.InnerHtml = DateTime.Now.ToString("r")
  End Sub
</Script>
<font size=6>The time is: <font color=red><span id="span1" runat="server"/></font></font>

このページは、単純に最初の要求で実行され、要求された時点の時刻を表示します。 その後、10 秒ごとに定期的に Cache からのページを処理します。たとえば、10 時 30 分 12 秒にページが要求された場合、そのページが再実行された後 10 秒ごとに出力される 値を見ることができます。

まとめ

Cache は、私たち ASP 開発者にとっては新しい機能です。しかし、Cache は簡単 に使用できる優れた機能です。API は、Application および Session の 単純なキー/値のペアの Dictionary に似ていますが、Application または Session とは異なり、Cache 内のアイテムは有効期限が切れる可能性がありま す。Application とは異なり、Cache はファイル、キーおよび時間に基づく依存関係以外 にも、コールバックをサポートしますが、これは Beta 2 後に説明することにします。また、 Cache は ASP.NET ページ出力キャッシュで、ASP.NET によっても使用されます。今後 のコラムでは、Beta 2 で導入される予定の新しいキャッシュ機能の一部 (部分ページ キャッ シングや Web サービス キャッシュなど) を説明するつもりです。さらに、コールバックのような より高度な機能の一部も見ていく予定です。


Rob Howard は Microsoft のプログラム マネージャです。彼がコードやコラムを書いていないときは、いつも東ワシントン川でフライ フィッシングを楽しんでいます。



Microsoft