図4●無駄な接続処理は行わない<BR>図左と図右は同じ処理内容であるが,「CONNECT」(データベースとの接続処理)の数が異なる。CONNECT処理は重い処理である。図左のように無駄なCONNECT処理がある場合,実行性能が低下する
図4●無駄な接続処理は行わない<BR>図左と図右は同じ処理内容であるが,「CONNECT」(データベースとの接続処理)の数が異なる。CONNECT処理は重い処理である。図左のように無駄なCONNECT処理がある場合,実行性能が低下する
[画像のクリックで拡大表示]
図5●無駄なSQL文の解析処理は行わない&lt;BR&gt;図左と図右は同じ処理内容であるが,SQL文の解析処理の回数が異なる。通常図左はSQL文の解析を2回行い,図右は1回しか行わない。図右のようにバインド変数を使えば,SQL文の解析処理回数が減り,実行性能が高まる
図5●無駄なSQL文の解析処理は行わない<BR>図左と図右は同じ処理内容であるが,SQL文の解析処理の回数が異なる。通常図左はSQL文の解析を2回行い,図右は1回しか行わない。図右のようにバインド変数を使えば,SQL文の解析処理回数が減り,実行性能が高まる
[画像のクリックで拡大表示]
図6●アプリケーションの挙動はミドルウエアに依存する&lt;BR&gt;「SELECT~FOR UPDATE NOWAIT」を実行させた例である。図左はミドルウエアに「Oracle Objects for OLE(OO4O)」を使った例で,図右は「OLEDB Provider  for ODBC Drivers(ODBC)」を使った例である。サンプル・プログラムはVisual Basicで記述した。OO4OではNOWAITオプションは有効であるが,ODBCではNOWAITオプションは無効になっている。(図中のプログラムはスペースの都合上,適宜改行を入れている)
図6●アプリケーションの挙動はミドルウエアに依存する<BR>「SELECT~FOR UPDATE NOWAIT」を実行させた例である。図左はミドルウエアに「Oracle Objects for OLE(OO4O)」を使った例で,図右は「OLEDB Provider for ODBC Drivers(ODBC)」を使った例である。サンプル・プログラムはVisual Basicで記述した。OO4OではNOWAITオプションは有効であるが,ODBCではNOWAITオプションは無効になっている。(図中のプログラムはスペースの都合上,適宜改行を入れている)
[画像のクリックで拡大表示]

ポイント3 接続処理は必要最小限にする

 データベースに対する接続処理は重い処理であるため,無駄な接続処理を実施していると実行性能が低下する。図4[拡大表示]左と右のSQL文は同じ処理内容であるが,同左は同右に比べて接続処理の回数が多い。接続処理回数が多い分,同左は実行性能が低い。

 接続処理に関しては,特にWebアプリケーションの開発において注意が必要である。データベースへの接続/切断処理は,一連の処理の前後に行うのが基本である。ところがWebアプリケーションではHTML*ページごとに処理が途切れるため,基本に従うとHTMLページ単位で接続処理を行わなければならない。

 この問題を解消するための機能が,多くのWebアプリケーション・サーバー(APサーバー)製品に備わるコネクション・プーリング*機能である。コネクション・プーリング機能を使えば,データベース接続情報をプールしておいて使いまわすことができる。APサーバーを使ってWebアプリケーションを開発する場合は,コネクション・プーリング機能を積極的に利用したい。

ポイント4 バインド変数を利用する

 SQL文は解析処理しなければ実行できないが,RDBMSにはSQL文の解析処理結果をキャッシュして再利用する仕組みが備わっている。解析結果をメモリー中に保存し,同じSQL文の解析処理を繰り返し行わないようにするのである。

 解析結果を再利用する仕組みはSQL文が同じ場合にのみ効果を発揮する。ここで重要なポイントは,SQL文が同じかどうかは,SQL文の処理内容ではなく,単にSQL文の文字列の比較で行うことである。大文字と小文字の違いがあっても異なるSQL文と判断されるが,逆に言えば,SQL文の文字列さえ同じであれば解析処理結果が再利用される。この特性を生かし,検索条件の数値だけが異なるSELECT文の解析処理を減らす方法がある。通常は検索条件の値が異なればSQL文の文字列は異なるが,条件値を変数で記述し,異なる条件値のSQL文であってもSQL文の文字列を同じにする方法である(図5[拡大表示])。このような変数を「バインド変数*」と呼ぶ。SQL文の文字列が同じなので,解析処理結果を再利用することが可能になる。

ポイント5 ミドルウエアの動きをつかんでおく

 データベース・アプリケーションの開発では,データベース接続ミドルウエアを利用することが多い。例えばVisual BasicのプログラムからOracleに接続する場合,米Oracleのミドルウエア「Oracle Objects for OLE(以下,OO4O)」や「Oracle Provider for OLE DB(以下,OLE DB)」,米Microsoftのミドルウエア「OLE DB Provider for ODBC Drivers(以下,ODBC)」などが利用可能である。

 これらのミドルウエアは高レベルのAPIを提供するので開発生産性の向上に役立つが,同じSQL文であってもミドルウエアが異なると挙動が違ってくることがある。ここでは,ポイント1で取り上げた「SELECT~FOR UPDATE NOWAIT」文を例に,ミドルウエアの違いによる挙動の違いを見てみる。図6[拡大表示]の2つのプログラムは,SELECT~FOR UPDATE NOWAIT文を発行するVisual Basicのプログラムである。同じ処理内容のプログラムであるが,利用しているデータベース接続ミドルウエアだけが異なる。図左がOO4Oで,図右がODBCである。

 図6の下段はそれぞれの実行結果である。対象データが別のユーザーにロックをかけられていない場合は同じ挙動を示すが,対象データが別のユーザーにロックをかけられている場合は挙動が異なる。OO4Oはリソース・ビジーのエラーになるが,ODBCはデータ・ロック中になる。ミドルウエアを使わなければリソース・ビジーのエラーになるケースなので,ODBCの動きが期待した動きと異なっている。ODBCを使った場合,NOWAITオプションが機能しない。ちなみにOLE DBでは,OO4Oと同じ挙動を示す。

 ODBCではNOWAITオプションは機能せず,コマンド・エラーにもならない。このような場合,ミドルウエアの動きを知っておかなければ,原因を突き止めるのに苦労する。データベース接続ミドルウエアを利用する場合は,利用するミドルウエアの機能や仕様を十分に確認しておこう。

ポイント6 本番データをテスト時に使う

 データベース・アプリケーションにおいて,カットオーバー後にトラブルを起こさないようにするポイントの一つは,本番データでしっかりテストしておくことである。本番データを使ってテストすれば,SQL文の実行時間が把握でき,SQL文の挙動が事前に確認しやすくなる。

 JavaやVisual Basicなどで組んだプログラムは,テスト時にステップ実行などのデバッグ環境を利用すれば,プログラムの実行途中の状態を確認できる。それに対してSQL文は,RDBMS内部で動いて結果だけを返すため,実行途中の状態を確認することは難しい。想定されるデータを用意してSQL文の単体テストを行うことが必要になり,開発の早い段階で本番に近いデータを用意できればテストがスムースに進む。

ポイント7 SQLコマンドの仕様を確認する

 最後のポイントは,新バージョンのRDBMS製品を利用する場合,主たる新機能だけでなく,SQLコマンドや関数の仕様を確認することである。SQLコマンドや関数が機能強化されたり制限が緩和されたりしていれば,今まで実現できなかったことが実現できたり,システム開発において役立つ場合がある。

 実際筆者の経験として,今まで顧客にSQLコマンドや関数の仕様上の制限から「できません」といっていたことが新バージョンで「できる」ようになり,顧客に後から提案するようなケースが多々ある。新バージョンのRDBMSを使うことがあれば,SQLコマンドや関数のマニュアルを一読してほしい。


玉川 敏一
シーズ・ラボ ITソリューション部 セクションマネージャー