既定のページング処理とカスタムのページング処理のパフォーマンスを比較する
本稿のサンプルファイルに収められている(50,000個のレコードから成るテーブルを持つ)データベースで既定のページング処理とカスタムのページング処理のパフォーマンスを比較するために、私はSQLプロファイラとASP.NETのトレース機能の両方を使って相対的なパフォーマンスの差を突き止めました(このテストは、私のコンピュータ上で、バックグラウンドで他のプロセスを実行したりしながら行ったものなので、あまり厳密とは言えません。この結果を結論とは言い難いですが、2つのアプローチにおけるパフォーマンスの差を見れば、カスタムのページング処理が優れていることがはっきり分かると思います)。
| 既定のページング処理 | カスタムのページング処理 | ||
| (Employeesからすべてのレコードを選択する) | (Employeesから1ページ分のレコードを選択する) | ||
| 時間(秒) | 読み取り回数 | 時間(秒) | 読み取り回数 |
| 1.455 | 383 | 0.003 | 29 |
| 1.405 | 383 | 0.000 | 29 |
| 1.434 | 383 | 0.000 | 29 |
| 1.394 | 383 | 0.003 | 29 |
| 1.365 | 383 | 0.003 | 29 |
| 平均:1.411 | 平均:383 | 平均:0.002 | 平均:29 |
| 既定のページング処理 | カスタムのページング処理 | SqlDataSourceのキャッシング |
| (Employeesからすべてのレコードを選択する) | (Employeesから1ページ分のレコードを選択する) | (すべてのレコードを選択してキャッシュに保管する) |
| ページ読み込み時間(秒) | ページ読み込み時間(秒) | ページ読み込み時間(秒) |
| 2.34136852588807 | 0.0259611207569677 | 2.39666633608461 |
| 2.35772228034569 | 0.0280046765720224 | 0.0431529705591074 |
| 2.43368277253115 | 0.0359054013848129 | 0.0443528437273452 |
| 2.43237562315881 | 0.0295534767686955 | 0.0442313199023898 |
| 2.33167064529151 | 0.0300096800012292 | 0.0491523364002967 |
| 平均:2.379363969 | 平均:0.029886871 | 平均:0.515511161 |
お分かりのように、カスタムのページング処理は既定のページング処理よりも、およそ2桁速いです。データベースレベルでは、GetEmployeesSubset(@startRowIndex int, @maximumRows int)ストアドプロシージャの処理速度は、「Employees」テーブルからすべてのレコードを返すシンプルなSELECTステートメントの約470倍です。ASP.NETレベルでは、カスタムのページング処理の速度は既定のページング処理の約120倍です。時間の短縮、つまりパフォーマンスの向上は、おそらく両方のアプローチに共通する高い作業負荷、すなわち、データベース接続を確立したりコマンドを実行したりする処理によるものでしょう。とはいえ、2桁という差はパフォーマンスの世界では非常に大きい差です。この差は、データ容量がもっと大きかったり、サーバで読み込みのようなことを実行したりすると、一層拡大すると思われます。
SqlDataSourceのキャッシングでは、キャッシュが空であるとデータベースにアクセスしてすべてのレコードを取得しなければならないため、それだけ時間がかかります。キャッシュの再読み込みの頻度は、Webサーバ上の空きリソース(利用できるリソースが少ないと、キャッシュ内のDataSetが削除されることがあります)とキャッシュの有効期限ポリシーによって異なります。ただし、データをキャッシュした後は、パフォーマンスが著しく向上し、カスタムのページング処理のアプローチに匹敵します。0.516秒という平均時間は、キャッシュ内のデータで処理できる要求の数が増えるにつれて、0.05秒に近づきます。
まとめ
ASP.NET 1.xのDataGridと同様、2.0のGridViewでは、既定とカスタムの2つのページング処理を利用することができます。既定のページング処理は、簡単に設定できますが、1ページ分のデータを表示するたびにデータベースに対してクエリを再実行しなければなりません。しかし、カスタムのページング処理は、表示する必要があるレコードのみを賢く取得するので、パフォーマンスを大幅に向上させることができます。SQL Server 2005では、ROW_NUMBER()機能を含め、結果を順序付けする機能を使うことで、任意のページに対するレコードの正しいサブセットの取得を簡易化しています。
作成中のWebアプリケーションを将来的に拡張する必要がある場合や、ページング処理してユーザーに表示するデータセットが遅かれ早かれ大きくなる可能性が高い場合には、カスタムのページング処理を実装する必要があります。
それでは、ハッピープログラミング!
参考資料
- ScottGu's Blog 『Paging through lots of data efficiently (and in an Ajax way) with ASP.NET 2.0』
- TheServerSide.NET 『Build a Data Access Layer with the Visual Studio 2005 DataSet Designer』
- 4GuysFromRolla.com 『Using Strongly-Typed Data Access in Visual Studio 2005 and ASP.NET 2.0』
- MSDN 『Caching Data with the SqlDataSource Control』
- 4GuysFromRolla.com 『Returning Ranked Results with Microsoft SQL Server 2005』
- 4GuysFromRolla.com 『Sorting Custom Paged Results』
