Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

ODP.NET パフォーマンスチューニング 第1回

Oracle Data Provider for .NET(ODP.NET)の活用

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/07/31 14:00

.NETアプリケーションからOracleへ接続する場合、Oracle Data Provider for .NET(ODP.NET)には、Oracleへのアクセスを高速化させるための様々な機能が実装されています。これらの機能を活用することにより、ハイパフォーマンスなデータアクセスアプリケーションを開発することが可能です。今回は、ODP.NETのパフォーマンスチューニングについて説明します。

目次

はじめに

 .NETアプリケーションからOracleへ接続するための最善の方法は、Oracle社が提供している「Oracle Data Provider for .NET」(以下、ODP.NET)です。今回は、ODP.NETを利用してデータベースへのアクセスを高速化する手法を説明します。

対象読者

  • Visual Basic、もしくはC#を使ってプログラムを作ったことのある人。
  • Oracleデータベース対応アプリケーション開発に興味のある人。

データベースへのアクセス速度を向上させる方法

 データベースへのアクセス速度を上げるにはさまざまな方法がありますが、今回は以下の方法を説明します。

  1. コネクションプーリングを利用する
  2. データベースとのラウンドトリップを少なくする
  3. SQLの解析を少なくする

コネクションプーリングを利用する

 コネクションプーリングとは、コネクション(接続)をプール(保持)しておくことです。コネクションプーリングを利用しないと、データベースに対して都度、接続を確立します。この場合、多数の接続があった際にかなりの負荷がデータベースサーバーにかかります。コネクションプーリングでは、あらかじめ接続を確立しておき、必要なときにプールから取り出して使います。そして、接続が終了したら、再びプールにコネクションを戻します。要はコネクションを使い回して効率よく接続するのがコネクションプーリングです。

 ODP.NETでは、コネクションプーリングがデフォルトで有効になっています。コネクションプーリングを明示的に利用したい場合は、次のように接続文字列属性を指定します。コネクションプーリングの設定を変更することにより、コネクションプーリング利用時のパフォーマンスチューニングを行うことが可能です。以下、コネクションプーリングに関連する接続文字列属性です。

表1
設定項目 内容 デフォルト値
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ステートメントの利用例(VB.NET)
Using conn As New OracleConnection( _
  "User ID=scott;Password=tiger;Data Source=orcl10gr2")
  conn.Open()
  'データアクセス処理
  '------------------
End Using
Usingステートメントの利用例(C#)
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プロパティを設定しています。

OracleCommandのFetchSize指定例(VB.NET)
' コマンドの準備
Dim cmd As New OracleCommand

'FetchSizeを128kに設定
cmd.FetchSize = 131072
OracleCommandのFetchSize指定例(C#)
// コマンドの準備
OracleCommand cmd = new OracleCommand();

//FetchSizeを128kに設定
cmd.FetchSize = 131072;

 また、FetchSizeプロパティの指定は、ツールボックスのコントロールを使用してプログラミングしている場合には、GUI上のプロパティウィンドウからも設定できます。

FetchSizeプロパティの指定
FetchSizeプロパティの指定

 あらかじめ取得するデータのレコード・サイズが不明な場合には、OracleCommandオブジェクトのRowSizeプロパティを使用し、1行あたりのバイト数を取得して設定できます。

OracleCommandのRowSizeプロパティについて
OracleCommandのRowSizeプロパティについて

 OracleCommandオブジェクトのRowSizeプロパティには、SELECT文の実行後に行サイズ(byte)が移入されます。OracleCommandオブジェクト、もしくはOracleDataReaderFetchSizeプロパティは、このRowSizeプロパティに各サーバー・ラウンドトリップでフェッチする行数を掛けた値に設定できます。以下のコードではRowSizeプロパティを使用して10行づつフェッチする設定を行っています。

RowSizeプロパティを使用し10行単位でフェッチするコード(VB.NET)
'OracleDataReaderオブジェクトを作成する
Dim rdr As OracleDataReader = cmd.ExecuteReader

'OracleCommandをExecutionした後に、RowSizeを取得。
'10行分のフェッチサイズを設定
rdr.FetchSize = cmd.RowSize * 10
RowSizeプロパティを使用し10行単位でフェッチするコード(C#)
//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プロパティを指定します。

LOB型列に対するフェッチサイズの指定(VB)
cmd.InitialLOBFetchSize = 32767
LOB型列に対するフェッチサイズの指定(C#)
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文の数を指定します。設定する値は次のとおりです。

表2
説明
0 データ・アダプタはすべてのSQL文を単一のバッチで実行します。
1 この値はバッチの更新を無効にし、SQL文は一度に1つずつ実行されます。
n(ただしn > 1) データ・アダプタは、一度にn個のバッチのUpdateBatchSizeオペランドを実行します。

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 日本オラクル 大田(オオタ ヒロシ)

    日本オラクル株式会社 Oracle Directテクニカルサービス部所属。開発者の視点から、Oracle Databaseの機能を最大限に活かすための手法を日々研究しながら、プリセールス活動やオンラインセミナー等による情報発信を行う。現在はWindows Server上でのOracle製品活用を推進...

バックナンバー

連載:Oracle Tips

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5