連載
» 2005年01月27日 00時00分 公開

ODP.NETのデータアクセス・チューニングODP.NETファーストステップ(3)(2/4 ページ)

[大田浩,日本オラクル]

OracleDataReader使用時のパフォーマンス・チューニング

 アプリケーションのパフォーマンスは、アプリケーションがフェッチする必要のある行数と、それらの取得に必要なデータベース・ラウンドトリップの数によって決まります。OracleDataReaderオブジェクトを使用して、Oracleデータベースからデータを取得する際に、データベース・ラウンドトリップを減らす方法として、FetchSizeプロパティを調整する方法があります。

 FetchSizeプロパティは、1回のデータベース・ラウンドトリップでフェッチされたデータをキャッシュするために、ODP.NETで割り当てられるメモリの合計サイズをbyteで表します。FetchSizeプロパティは、状況に応じてOracleCommandまたはOracleDataReaderのどちらにも設定できます。FetchSizeプロパティの値が小さいと、データベース・ラウンドトリップが必要以上に発生して、アプリケーションのパフォーマンスが落ちてしまいます(図1)。

図1 FetchSizeプロパティの値が小さい場合 図1 FetchSizeプロパティの値が小さい場合

 FetchSizeプロパティの値を適切に設定することにより、データベース・ラウンドドリップを最小限に抑え、アプリケーションのパフォーマンスを向上させることが可能です(図2)。

図2 FetchSizeプロパティの値を適切に設定してある場合 図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からPL/SQLを利用

 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#)

次ページへ続く)

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。