コラム: JDBC - PreparedStatementを使って高速化



JDBC - PreparedStatementを使って高速化

本コラムの対象:
JDBCを使用して、データベースプログラムを作成したことがある方。

1.はじめに

データベースの操作はその手法によってパフォーマンスに大きく影響をあたえます。特に、今日のシステム開発はデータベースなしに語れないほどであり、重要であると言えます。

ここでは、JDBCを使用したデータベース操作のトピックから、PreparedStatement を使用した高速化について説明します。このコラムで使用したサンプルでは、PreparedStatementの利用で最大3.8倍高速になりました。

2.Statementとは

Javaプログラムがデータベースに接続すると、対応するConnectionオブジェクトを一つ取得します。Statementは、「Connection(データベース接続)を使用してSQL文を送信するコンテナ」の役割を持ちます。


図1: データベースとJDBCの対応

上の図のようにしてユーザとクライアントプログラムを比べると、JDBCドライバはユーザが使用するプログラムであるとイメージできます。

3.Statementの種類

JDBCでは、以下の3種類のStatementがインタフェースとして定義されています。

 ・java.sql.Statement
 ・java.sql.PreparedStatement
 ・java.sql.CallableStatement(今回は割愛)

StatementPreparedStatementの違いは、SQL文をあらかじめコンパイルしておくこと(これをプリコンパイルと言います)が可能であるかどうかにあります。この違いがあるため、一般にStatementよりもPreparedStatementを使用する方が高速であると言われています。
以下は、Oracle9iにおけるStatementPreparedStatementの速度比較です。
(実験の詳細はこちら


グラフ: StatementとPreparedStatementの速度比較(※上の図をクリックすると拡大します)

グラフを見ると、明らかにPreparedStatementの方が実行時間が短く、高速であることがわかります。
なぜ、上記のようにPreparedStatementは高速なのでしょうか?


4.PreparedStatementがStatementよりも高速になる理由

データベースでは、SQL文(ここではSELECT, INSERT, DELETE, UPDATEに限定します)を実行する際に、いくつかのステップを踏んで処理を行います。

 (1) SQL文の構文チェック、権限チェック
 (2) 検索方法の特定、コンパイル
 (3) データの検索、変更を実施

ここで、多くのデータベースでは効率化の為に(2)の結果とSQL文をキャッシュに保存します。以降、キャッシュに存在するSQL文は検索方法が特定されているものとし、(2)を実施することなく(3)の処理に移れる為、効率的に処理をすることが可能になります。

ただし、実行するSQL文がキャッシュに保存されているSQL文にヒットする為には、文字列全体が「完全に一致する」必要があります。

例を挙げて考えてみましょう。

以下のSQL文 a) を実行すると、a) の文字列がキャッシュに保存されます。

  a) SELECT * FROM A_TABLE WHERE ID=2

Statementを使用した場合は、SQL文を直接与えて実行する為、以下の b)、c) などはa) のキャッシュにヒットしません(図2の上側)。

 ■検索条件の値が異なるSQL文
  b) SELECT * FROM A_TABLE WHERE ID=1
  c) SELECT * FROM A_TABLE WHERE ID=5

一方で、PreparedStatementを使用した場合、SQL文を以下のように書くことが出来ます。

  d) SELECT * FROM A_TABLE WHERE ID=?  ← "?"はバインド変数

このようにSQL文を記述すると、データベースのキャッシュには上記 d) の文字列が保存されます。あとは、SQL文の実行時に"?"の値を1や5などいくつに決定しても、d) のキャッシュにヒットするようになります(図2の下側)。

このように、条件の値が異なる検索などではキャッシュの利用効率が上がる分、処理が高速になるのです。

StatementとPreparedStatementの処理の違い
図2: Statement と PreparedStatement の処理の違い

5.まとめ

以上から、繰り返し検索を行う場合はPreparedStatementが高速化の点で高い効果を発揮することがわかります。
実験結果からも、高速化率は検索ループ回数が増えるにしたがってより高くなっています。

実験したプログラムではSELECTのみでキャッシュを同じSQLの為だけに使用しましたが、追加や更新が発生する実際のシステムでも効果はあります。
PreparedStatementを使用するようにシステムを設計すると、例えば多数のアクセスが発生するようなシステムにおいても、負荷を低減できることでしょう。

Page Top

注意:本文書の内容に誤りがあり、またこの文書によって不利益を被っても、
Acroquest Technology 株式会社は一切関知いたしません。

  • 現象別Index
  • 原因別Index

Find Bugsバグ詳細

Find Bugs Bug Descriptions日本語版

RSSで更新情報を取得する

RSSとは、ホームページの更新情報を配信する為のフォーマットです。
RSSを利用すると、登録したページの情報が更新された場合に、更新情報を自動的に受け取る事ができます。

詳細

弊社小森が執筆致しました

Javaでオブジェクト指向開発

Javaプログラミング言語習得において、新人プログラマーの最初の障害は「オブジェクト指向の壁」です。
本書は、Javaのソフトウェア開発を中心に事業を発展させてきたAcroquest社の新人教育セミナーを加筆・書籍化したもので、大卒の新人に対して、ゼロからJava言語を教えてきた実績をフィードバックしています。

メールマガジン配信中

Javaトラブルシューティングのメルマガをはじめました!是非ご購読ください

詳細