- PR -

JDBCでの配列フェッチについて

1
投稿者投稿内容
くりお
常連さん
会議室デビュー日: 2004/01/30
投稿数: 34
投稿日時: 2004-02-01 15:58
JDBCにて、SQLの結果を配列フェッチを行うことは可能なのでしょうか?

通常JDBCを用いて検索処理を行う場合、
java.sql.ResultSet rs = st.executeQuery();
while ( rs.next() ) {
int nBookID = rs.getInt("BookID");
String strTitle = rs.getString("Title");
int nPrice = rs.getInt("Price");
}

とループしてResultSetの値を格納すると思うのですが、
配列として件数を指定して、一気に値を格納したいと考えています。

どなたかご存知の方教えていただけないでしょうか?
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2004-02-02 11:28
引用:

くりおさんの書き込み (2004-02-01 15:58) より:
JDBCにて、SQLの結果を配列フェッチを行うことは可能なのでしょうか?



配列フェッチをしたいという目的は何でしょうか?

データベースアクセス回数を減らすことで、N/Wラウンドトリップ回数を減らし、パフォーマンスアップを図りたいということなら、ResultSet#setFetchSize(int) が使えます。

フェッチサイズがいくつであっても、JDBCコードは変更の必要はありません。
JDBCドライバが内部的に自動キャッシュするだけで、アプリケーションに対しては透過的に働くからです。

ただしこれがどう実装されるかはデータベースやJDBCドライバの種類によるかもしれないので、マニュアルなどで確認が必要だと思います。

もし単にJavaのループをなくしたいということであれば分かりません。
くりお
常連さん
会議室デビュー日: 2004/01/30
投稿数: 34
投稿日時: 2004-02-04 01:44
ご回答ありがとうございます。

配列フェッチの目的は
・ループを使用しない。
・カーソルDBアクセスの削減
による性能向上を考えていました。

ResultSet rs = st.executeQuery();
で実行した結果HITする件数が20,000件だったら、20,000件メモリにロードされるのですか?
※そんなSQLを発行するなと言うのは置いておいて。

もしそうなのであれば、今度はメモリ不足+FullGCが発生し性能低下を起こしそうですね。
通常は「ResultSet#setFetchSize」でフェッチのサイズを指定するものなのですかねぇ。
とんび
常連さん
会議室デビュー日: 2003/07/11
投稿数: 32
投稿日時: 2004-02-04 02:37
引用:

くりおさんの書き込み (2004-02-04 01:44) より:
ご回答ありがとうございます。

配列フェッチの目的は
・ループを使用しない。
・カーソルDBアクセスの削減
による性能向上を考えていました。


 どうも、配列フェッチの意味を間違えて使われてるような気がするのですが。
一般的な配列フェッチというのは、JDBCドライバがResultSetのnextメソッドを呼びたすたびに、
DBMSから結果を取得するのではなく、いくつかの行をまとめて取得することによって
性能を向上させることだと思うのですが。
 この場合の配列フェッチは、あくまで、JDBCドライバ内部の動作なので、JDBCを利用する側からはResultSet#setFetchSizeを指定する以外普段の利用方法と変わりません。

 くりおさんのいわれている配列フェッチとはそうではなくて、Queryの結果を
配列として受け取りたいということなのではないでしょうか。
もしそうだとすると、JakartaのDBUtilとかを使えば出来るかもしれませんが、
その場合、ふつうにJDBC使うより遅くなってしまいます(DBUtilならたいして遅くならないようですが)。

引用:

ResultSet rs = st.executeQuery();
で実行した結果HITする件数が20,000件だったら、20,000件メモリにロードされるのですか?
※そんなSQLを発行するなと言うのは置いておいて。

もしそうなのであれば、今度はメモリ不足+FullGCが発生し性能低下を起こしそうですね。
通常は「ResultSet#setFetchSize」でフェッチのサイズを指定するものなのですかねぇ。


 フェッチのサイズを指定してもたいして性能向上が期待できるとは思えないので
ResultSet#setFetchSizeを使ったことはないです。
そんなに速度が問題になるなら、もっと別のチューニングを考えないとだめだと思います。

 くりおさんのいわれている、20,000件ヒットするようなSQLを発行する必要が本当にあるのかどうか検討するのが先だと思うのですが。
yuzy
大ベテラン
会議室デビュー日: 2002/02/14
投稿数: 117
投稿日時: 2004-02-04 09:12
> くりおさんのいわれている、20,000件ヒッ>トするようなSQLを発行する必要が本当にあるのかどうか検討するのが先だと思うのですが。

同感です。
コンサルティングをやっていて、お客様から同様の要求があることがたびたびあります。
そのときに聞いているんですが、「では、その20,000件の中の12,345件目を見たい
という要求はあるんですか?」
(つまり本当に必要なデータなの? 件数だけ見たいんなら別の取り方があるし。)
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2004-02-04 10:35
引用:

とんびさんの書き込み (2004-02-04 02:37) より:
 フェッチのサイズを指定してもたいして性能向上が期待できるとは思えないので
ResultSet#setFetchSizeを使ったことはないです。



そこらへんは環境依存かなと思います。
データベースの種類や構成によっては、プリフェッチサイズを大きくすることで相当大きなパフォーマンスメリットがありますよ。
びしばし
大ベテラン
会議室デビュー日: 2002/03/13
投稿数: 181
投稿日時: 2004-02-04 14:43
本旨に沿っていないかもしれませんが、DBUtils についてです。

引用:

とんびさんの書き込み (2004-02-04 02:37) より:
 くりおさんのいわれている配列フェッチとはそうではなくて、Queryの結果を
配列として受け取りたいということなのではないでしょうか。
もしそうだとすると、JakartaのDBUtilとかを使えば出来るかもしれませんが、
その場合、ふつうにJDBC使うより遅くなってしまいます(DBUtilならたいして遅くならないようですが)。



できます。各レコードを Object[]、Bean、Object[] を要素に持った List、Bean を要素に持った List などで受け取ることができます。スピードもあまり遅くならないようですよ。

参考: http://www02.so-net.ne.jp/~kikuta/dbu/ (ほか、日本語の情報はいくつかあります)

しかし、これは該当全件をメモリ上に展開しようとするので「20,000件ヒットする SQL」には向きませんね。
# Iterator を返すハンドラを自作すればいいのだろうけれど。

DBUtils のソースは難しくなく改造して利用することも容易なので、ResultSet をガリガリいじり倒している人には試してみる価値があるかと思います。
1

スキルアップ/キャリアアップ(JOB@IT)