はじめに
.NETアプリケーションからOracleへ接続するための最善の方法は、Oracle社が提供している「Oracle Data Provider for .NET」(以下、ODP.NET)です。今回は、ODP.NETを利用してデータベースへのアクセスを高速化する手法を説明します。
対象読者
- Visual Basic、もしくはC#を使ってプログラムを作ったことのある人。
- Oracleデータベース対応アプリケーション開発に興味のある人。
データベースへのアクセス速度を向上させる方法
データベースへのアクセス速度を上げるにはさまざまな方法がありますが、今回は以下の方法を説明します。
- コネクションプーリングを利用する
- データベースとのラウンドトリップを少なくする
- SQLの解析を少なくする
コネクションプーリングを利用する
コネクションプーリングとは、コネクション(接続)をプール(保持)しておくことです。コネクションプーリングを利用しないと、データベースに対して都度、接続を確立します。この場合、多数の接続があった際にかなりの負荷がデータベースサーバーにかかります。コネクションプーリングでは、あらかじめ接続を確立しておき、必要なときにプールから取り出して使います。そして、接続が終了したら、再びプールにコネクションを戻します。要はコネクションを使い回して効率よく接続するのがコネクションプーリングです。
ODP.NETでは、コネクションプーリングがデフォルトで有効になっています。コネクションプーリングを明示的に利用したい場合は、次のように接続文字列属性を指定します。コネクションプーリングの設定を変更することにより、コネクションプーリング利用時のパフォーマンスチューニングを行うことが可能です。以下、コネクションプーリングに関連する接続文字列属性です。
設定項目 | 内容 | デフォルト値 |
Min Pool Size | プール内の接続の最小数 | 1 |
Max Pool Size | プール内の接続の最大数 | 100 |
Incr Pool Size | プール内のすべての接続が使用された場合に作成される新しい接続の数 | 5 |
Decr Pool Size | 未使用の確立済接続量が過剰となり、クローズされる接続数 | 1 |
Connection Lifetime | 接続の最大存続期間(秒) | 0 |
Connection Timeout | プールから使用可能な接続を待機する最大時間(秒) | 15 |
Validate Connection | プールを使用している接続の検証 | false |
接続文字列属性を設定する際の注意点は、以下のとおりです。
- 接続文字列属性の記述順を変更しても、新規にコネクションプールが生成されません。
- 接続文字列属性の値がデフォルト値の場合は、新規にコネクションプールが生成されません。
- 接続文字列属性の値を動的に設定することは推奨されません。
また、コネクションのClose/Disposeは明示的に行ってください。.NET Framework 2.0の場合は、Usingステートメントを利用して、次のように記述できます。
Using conn As New OracleConnection( _ "User ID=scott;Password=tiger;Data Source=orcl10gr2") conn.Open() 'データアクセス処理 '------------------ End Using
using(OracleConnection conn = new OracleConnection( "User ID=scott;Password=tiger;Data Source=orcl10gr2")){ conn.Open(); //データアクセス処理 //------------------ }
データベースとのラウンドトリップを少なくする
アプリケーションのパフォーマンスは、アプリケーションがフェッチする必要のある行数と、それらの取得に必要なデータベース・ラウンドトリップの数によって決まります。データベース・ラウンドトリップの数が多いと、それだけデータベースサーバーとの通信が発生し、結果としてアプリケーションのパフォーマンスが落ちてしまいます。以下、データベース・ラウンドドリップを少なくする方法を説明します。
FetchSizeの指定
データベース・ラウンドトリップを少なくする方法として、一回のデータベース・ラウンドトリップで取得するデータの行数を増やす方法があります。OracleCommandまたはOracleDataReaderに用意されている、FetchSize
プロパティを設定することにより、取得するデータの行数を調整することが可能です。FetchSize
プロパティは、1回のデータベース・ラウンドトリップでフェッチされたデータをキャッシュするために、ODP.NETで割り当てられるメモリの合計サイズをバイト単位で表します。デフォルト値は65,536バイトになります。下記では、OracleCommand
オブジェクトのFetchSize
プロパティを設定しています。
' コマンドの準備 Dim cmd As New OracleCommand 'FetchSizeを128kに設定 cmd.FetchSize = 131072
// コマンドの準備 OracleCommand cmd = new OracleCommand(); //FetchSizeを128kに設定 cmd.FetchSize = 131072;
また、FetchSize
プロパティの指定は、ツールボックスのコントロールを使用してプログラミングしている場合には、GUI上のプロパティウィンドウからも設定できます。
あらかじめ取得するデータのレコード・サイズが不明な場合には、OracleCommand
オブジェクトのRowSize
プロパティを使用し、1行あたりのバイト数を取得して設定できます。
OracleCommand
オブジェクトのRowSize
プロパティには、SELECT文の実行後に行サイズ(byte)が移入されます。OracleCommand
オブジェクト、もしくはOracleDataReader
のFetchSize
プロパティは、このRowSize
プロパティに各サーバー・ラウンドトリップでフェッチする行数を掛けた値に設定できます。以下のコードではRowSize
プロパティを使用して10行づつフェッチする設定を行っています。
'OracleDataReaderオブジェクトを作成する Dim rdr As OracleDataReader = cmd.ExecuteReader 'OracleCommandをExecutionした後に、RowSizeを取得。 '10行分のフェッチサイズを設定 rdr.FetchSize = cmd.RowSize * 10
//OracleDataReaderオブジェクトを作成する OracleDataReader dr = cmd.ExecuteReader(); // OracleCommandをExecutionした後に、RowSizeを取得。 // 10行分のフェッチサイズを設定 rdr.FetchSize = cmd.RowSize * 10;
FetchSize
プロパティを微調整することで、アプリケーションは、メモリ使用率、および1回のデータベース・ラウンドトリップでフェッチされる行数を制御して、パフォーマンスを向上させることができます。この、FetchSize
プロパティに設定する値ですが、大きく設定すると、クライアント側のメモリを必要以上に消費してしまい、少なすぎるとデータベースのラウンドトリップが多発してしまいます。アプリケーションの特性を考慮し、適切なFetchSizeを指定してください。
LOB型フィールドでのFetchSizeの指定について
LOBとはラージオブジェクト(Large Object)のことで、通常ギガバイト程度までの大きさのデータになります。LOBはそのデータ型としてBLOB(Binary Large Object)とCLOB(Character Large Object)の2種類に分類され、Oracle データベースではBLOB、CLOB共に9iで最大4GB、10gではブロックサイズにより最大8~128TBまでのデータを格納できます。ODP.NETでは、OracleデータベースのLOBデータをネイティブに取り扱うデータ型が用意されています。このLOB型フィールドに格納されている値の取得に関しても、FetchSizeを指定することによりパフォーマンスを向上させることが可能です。LOB型列に対するフェッチサイズの指定は、OracleCommand
クラスのInitialLobFetchSize
プロパティを指定します。
cmd.InitialLOBFetchSize = 32767
cmd.InitialLOBFetchSize = 32767;
InitialLobFetchSize
プロパティに関しては、Oracle Database 10g Release 2(以下、Oracle 10g R2)から大幅に改善されています。Oracle 10g R2より前のバージョンとOracle 10g R2のLOB型フィールドでのFetchSizeの指定についての違いについては、Oracle Data Provider for .NET開発者ガイドの、「OracleDataReaderオブジェクトからのデータの取得」の章を参照してください。
バッチ更新について
OracleDataAdapter
クラスのUpdateBatchSize
プロパティを指定することにより、OracleDataAdapter.Update
メソッドがコールされた場合のバッチ処理を可能にします。UpdateBatchSize
は、ラウンドトリップごとにOracleデータベースを更新するDataSet内の行数を示す、数値プロパティです。このプロパティは、バッチ処理サポートを有効または無効にする値を指定し、データベースへの1回のラウンドトリップで実行できるSQL文の数を指定します。設定する値は次のとおりです。
値 | 説明 |
0 | データ・アダプタはすべてのSQL文を単一のバッチで実行します。 |
1 | この値はバッチの更新を無効にし、SQL文は一度に1つずつ実行されます。 |
n(ただしn > 1) | データ・アダプタは、一度にn個のバッチのUpdateBatchSizeオペランドを実行します。 |