アプリケーションのパフォーマンスは、アプリケーションがフェッチする必要のある行数と、それらの取得に必要なデータベース・ラウンドトリップの数によって決まります。OracleDataReaderオブジェクトを使用して、Oracleデータベースからデータを取得する際に、データベース・ラウンドトリップを減らす方法として、FetchSizeプロパティを調整する方法があります。
FetchSizeプロパティは、1回のデータベース・ラウンドトリップでフェッチされたデータをキャッシュするために、ODP.NETで割り当てられるメモリの合計サイズをbyteで表します。FetchSizeプロパティは、状況に応じてOracleCommandまたはOracleDataReaderのどちらにも設定できます。FetchSizeプロパティの値が小さいと、データベース・ラウンドトリップが必要以上に発生して、アプリケーションのパフォーマンスが落ちてしまいます(図1)。
図1 FetchSizeプロパティの値が小さい場合
FetchSizeプロパティの値を適切に設定することにより、データベース・ラウンドドリップを最小限に抑え、アプリケーションのパフォーマンスを向上させることが可能です(図2)。
図2 FetchSizeプロパティの値を適切に設定してある場合
FetchSizeプロパティがOracleCommandに設定されている場合、新しく作成されるOracleDataReaderにはOracleCommandのFetchSizeプロパティが継承されます。継承されたFetchSizeはそのままにすることも、変更してオーバーライドすることもできます。FetchSizeはデフォルトで65,536bytesです。OracleDataReaderのFetchSizeプロパティを指定するコードは以下になります。
Dim cnn As New OracleConnection( _
"user id=scott;password=tiger;data source=orcl")
Dim strSql As String = _
"select empno, ename, job, mgr, hiredate, " & _
"sal, comm, deptno from emp"
Dim cmd As New OracleCommand(strSql, cnn)
cnn.Open()
Dim dr As OracleDataReader = cmd.ExecuteReader
dr.FetchSize = 131072
While dr.Read
'データ読み込み処理
End While |
リスト7 FetchSizeの指定(VB.NET) |
OracleConnection cnn =
new OracleConnection(
"user id=scott;password=tiger;data source=orcl");
String strSql =
"select empno, ename, job, mgr, hiredate, " +
"sal, comm, deptno from emp";
OracleCommand cmd = new OracleCommand(strSql, cnn);
cnn.Open();
OracleDataReader dr = cmd.ExecuteReader();
dr.FetchSize = 131072;
while(dr.Read())
{
//データ読み込み処理
} |
リスト8 FetchSizeの指定(C#) |
OracleCommandオブジェクトのRowSizeプロパティには、SELECT文の実行後に行サイズ(byte)が移入されます。OracleCommandオブジェクト、もしくはOracleDataReaderのFetchSizeプロパティは、このRowSizeプロパティに各サーバ・ラウンドトリップでフェッチする行数を掛けた値に設定できます。例えば、FetchSizeをRowSize×10に設定すると、OracleDataReaderは各サーバ・ラウンドトリップごとに10行をフェッチします。
Dim cnn As New OracleConnection( _
"user id=scott;password=tiger;data source=orcl")
Dim strSql As String = _
"select empno, ename, job, mgr, hiredate, " & _
"sal, comm, deptno from emp"
Dim cmd As New OracleCommand(strSql, cnn)
cnn.Open()
Dim dr As OracleDataReader = cmd.ExecuteReader
dr.FetchSize = cmd.RowSize * 10
While dr.Read
'データ読み込み処理
End While |
リスト9 FetchSizeを10行分に指定(VB.NET) |
OracleConnection cnn =
new OracleConnection(
"user id=scott;password=tiger;data source=orcl");
String strSql =
"select empno, ename, job, mgr, hiredate, " +
"sal, comm, deptno from emp";
OracleCommand cmd = new OracleCommand(strSql, cnn);
cnn.Open();
OracleDataReader dr = cmd.ExecuteReader();
dr.FetchSize = cmd.RowSize * 10;
while(dr.Read())
{
//データ読み込み処理
} |
リスト10 FetchSizeを10行分に指定(C#) |
ODP.NETからOracleデータベースに格納されたストアドプロシージャ/ストアドファンクションを呼び出す方法と、PL/SQL配列(PL/SQL表)を使用してサーバ・ラウンドトリップを減らし、パフォーマンスを向上させる方法を説明します。
まず初めに、ストアドプロシージャの呼び出し方法を説明します。
手順1
「scott」ユーザーの「emp」表にアクセスするテスト用のストアドプロシージャを作成します。
create procedure calc_comm(p_empno in number,
p_comm out number) is
begin
select sal * comm / 100 into p_comm
from emp where empno = p_empno;
end calc_comm; |
リスト11 社員番号をパラメータで受け取り、該当する社員のコミッションを計算し、結果を出力パラメータに格納するプロシージャ |
手順2
上記のストアドプロシージャをコールするコードは以下になります。
Dim cnn As New OracleConnection( _
"user id=scott;password=tiger;data source=orcl")
Dim cmd As New OracleCommand("calc_comm", cnn)
cmd.CommandType = CommandType.StoredProcedure
Dim p_empno As OracleParameter = _
cmd.Parameters.Add("p_empno", _
OracleDbType.Int32, ParameterDirection.Input)
p_empno.Value = 7499
Dim p_comm As OracleParameter = _
cmd.Parameters.Add("p_comm", _
OracleDbType.Int32, ParameterDirection.Output)
cnn.Open()
cmd.ExecuteNonQuery()
MsgBox("Commission=" + p_comm.Value.ToString) |
リスト12 ストアドプロシージャの実行(VB.NET) |
OracleConnection cnn =
new OracleConnection(
"user id=scott;password=tiger;data source=orcl");
OracleCommand cmd = new OracleCommand("calc_comm", cnn);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter p_empno =
cmd.Parameters.Add("p_empno",
OracleDbType.Int32, ParameterDirection.Input);
p_empno.Value = 7499;
OracleParameter p_comm =
cmd.Parameters.Add("p_comm",
OracleDbType.Int32, ParameterDirection.Output);
cnn.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Commission=" + p_comm.Value.ToString()); |
リスト13 ストアドプロシージャの実行(C#) |
ストアドプロシージャを呼び出す際には、OracleCommandオブジェクトのCommandTypeプロパティをStoredProcedureとします。ストアドプロシージャへのパラメータの入出力の設定は、OracleParameterオブジェクトのDirectionプロパティで指定を行います。指定可能な値は、「Input」「InputOutput」「Output」「ReturnValue」です。
ReturnValueを指定して、ストアドファンクションから戻り値を取得する方法を説明します。
手順1
テスト用のストアドファンクションを作成します。
CREATE function SCOTT.get_comm(p_empno in number)
return numeric is p_retval numeric;
begin
select sal * comm / 100 into p_retval
from emp where empno = p_empno;
return p_retval;
end get_comm; |
リスト14 社員番号をパラメータで受け取り、該当する社員のコミッションを計算し、戻り値として返すストアドファンクション |
手順2
上記のストアドファンクションをコールするコードは以下になります。
Dim cnn As New OracleConnection( _
"user id=scott;password=tiger;data source=orcl")
Dim cmd As New OracleCommand("get_comm", cnn)
cmd.CommandType = CommandType.StoredProcedure
Dim p_retval As OracleParameter = _
cmd.Parameters.Add("p_retval", OracleDbType.Int32, _
ParameterDirection.ReturnValue)
Dim p_empno As OracleParameter = _
cmd.Parameters.Add("p_empno", OracleDbType.Int32, _
ParameterDirection.Input)
p_empno.Value = 7499
cnn.Open()
cmd.ExecuteNonQuery()
MsgBox("Commission=" + p_retval.Value.ToString) |
リスト15 ストアドファンクションの実行(VB.NET) |
OracleConnection cnn =
new OracleConnection(
"user id=scott;password=tiger;data source=orcl");
OracleCommand cmd = new OracleCommand("get_comm", cnn);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter p_retval =
cmd.Parameters.Add("p_retval", OracleDbType.Int32,
ParameterDirection.ReturnValue);
OracleParameter p_empno =
cmd.Parameters.Add("p_empno", OracleDbType.Int32,
ParameterDirection.Input);
p_empno.Value = 7499;
cnn.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Commission=" + p_retval.Value.ToString()); |
リスト16 ストアドファンクションの実行(C#) |
(次ページへ続く)