SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Oracle Tips

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

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


  • X ポスト
  • このエントリーをはてなブックマークに追加

SQLの解析を少なくする

 共有プールにキャッシュされた情報は、SQLが完全に同一の場合にのみ再利用されます。WHERE句に指定されている条件値が異なっている場合、もしくはSQLの意味が同一でもスペースの個数、改行位置、大文字、小文字など、少しでも異なっている場合には、違うSQLとして新たに解析されます。下表にSQLが共有されない例を示します。

表3
実行されたSQL文 共有されない理由
SELECT * FROM emp WHERE empno=7788; インスタンス起動後や、共有プールのフラッシュ後、初めて実行する場合は必ずSQLの解析が発生する
SELECT * FROM emp WHERE empno=8000; WHERE句に指定されている条件値が異なる
SELECT * FROM  emp WHERE empno=7788; スペースの個数が異なる
SELECT * FROM EMP WHERE empno=7788; 大文字、小文字が異なる

 上記のSQLはすべて違うSQLとして解析されます。どのような場合にSQLの解析が発生するのかを理解し、SQLの解析の発生を少なくすることを意識してください。解析済みのSQLを共有し、パフォーマンスを上げるには、次のような方法があります。

バインド変数の利用

 WHERE句に指定されている条件値が異なるため共有されない問題に関しては、パラメータ変数を使用することにより解決できます。パラメータ変数は、OracleParameterクラスを利用します。Where句に指定されている条件を次のようにハードコーディングすることなくパラメータ変数を使用することにより、SQLの解析をなくし、パフォーマンスを向上させることが可能です。

バインド変数の利用(VB.NET)
Dim cmd As New OracleCommand( _
  "SELECT * FROM emp WHERE empno=:pEmpNo", conn)
Dim pEmpNo As OracleParameter = _
  cmd.Parameters.Add("pEmpNo", _
    OracleDbType.Int32, ParameterDirection.Input)
pEmpNo.Value = 7369
バインド変数の利用(C#)
OracleCommand cmd = new OracleCommand(
  "SELECT * FROM emp WHERE empno=:pEmpNo", conn);
OracleParameter pEmpNo =
  cmd.Parameters.Add("pEmpNo",
    OracleDbType.Int32, ParameterDirection.Input);
pEmpNo.Value = 7369;

 しかし、ソースコードを変更するのが難しい場合には、Oracleの共有カーソル機能を使用することで、類似したSQLを内部的にバインド変数化し、解析結果を共有させることができます。共有カーソル機能を使用するためには、初期化パラメータ「CURSOR_SHARING」を設定します。設定可能な値と機能は次のとおりです。

表4
設定値 説明
FORCE リテラルがわずかに異なっても、同一のSQLとして共有します。
SIMILAR 実行計画が同一であれば、同一のSQLとして共有します。
EXACT 完全に同一のテキストを含むSQLのみ共有します(デフォルト値)。

 動的SQLを多用している場合、SIMILARやFORCEを指定するとパフォーマンスが向上する可能性があります。ただし、FORCEを指定した場合は実行計画次第でパフォーマンスが落ちる場合もありますので、パラメータを変更する前に十分にテストを行ってください。

 今まで説明したような、パラメータ変数を利用する方法と初期化パラメータ「CURSOR_SHARING」を設定する方法以外にも、ステートメント・キャッシングという機能を利用してSQLの再解析を防ぐことが可能です。

ステートメント・キャッシング

 ステートメント・キャッシュを利用することにより、同じSQL文を(場合によっては異なるパラメータ値を使用して)後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスを向上させることが可能です。

 ステートメント・キャッシュを利用するには、接続文字列属性で「Statement Cache Size」を指定します。この属性は、ODP.NETステートメント・キャッシュを有効化または無効化します。デフォルトでは、この属性は0に設定され、ODP.NETステートメント・キャッシュは無効です。0より大きい値に設定することで、ODP.NETステートメント・キャッシュが有効になり、指定された値は、接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。ステートメント・キャッシュの利用は、次のようにOracleへ接続するための接続文字列、「Statement Cache Size」に接続用にキャッシュできる文の最大数を指定します。

ステートメント・キャッシュを利用した接続文字列
"User Id=SCOTT;Password=TIGER;Data Source=ORCL;Statement Cache Size=100"

 ステートメント・キャッシュ利用時も、「SQLの解析を少なくする」で説明した時と同様に、パラメータ変数を使用しないと、別のSQLとして解析が行われてしまいますので、ステートメント・キャッシュ利用時は必ずパラメータ変数を使用してください。

おわりに

 ODP.NETにはデータベースへのアクセス速度を向上させるプロパティ、メソッドが多数用意されており、開発者はこれらの機能を上手に活用すれば、ハイパフォーマンスなデータベースアプリケーションを開発できます。次回も引き続きパフォーマンスを向上させるための様々な手法を説明しますので、ご期待ください!

参考資料

  1. Oracle Data Provider for .NET開発者ガイド

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Oracle Tips連載記事一覧

もっと読む

この記事の著者

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1503 2009/10/08 19:09

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング