• 締切済み

JDBCでの大量データ検索でResultsetの戻りが遅い

こんにちは JUNです。 サーブレットでJDBC経由で検索クエリを実行しているのですが、非常に処理が遅くて困っています。 そこでSQLの改善をしていますが、SQL plus上は早さが UPしてもJDBC経由にすると逆に遅くなったりします。 何故でしょうか。また何か考えられる原因がありましたら 教えて下さい。 ※クエリの見直しはほぼ限界に差し掛かっています。 環境: AIX4.3 Oracle version 8.0.5.1 Webshphere Application Server 3.0.2.2 JDK 1.18 データ数最大30万件取得。1レコード200バイト。

みんなの回答

  • yuji
  • ベストアンサー率37% (64/169)
回答No.4

はっきりいって30万件もあるデータを Web で見よう、ということ自体 間違っています。 仕様を見直した方がいいです。 うちで作るときは、だいたい上限件数(例:200)を決めておいて、 まず件数だけを取得し、それが上限件数以上だったら 検索条件を追加してもらって件数を少なくしてもらうような作りです。 上限件数以下だったらダウンロードさせます。 (ダウンロードさせるときも、サイズが大きいようなら圧縮して  からダウンロードさせた方がいいでしょう。) それと、JDKのバージョンですが、WebSphere 3.0.2.2をお使いの ようなので、1.1.8から 1.2.x に上げることはできません。 上げると動かなくなります。

jkz
質問者

補足

コメントありがとうございます。 見るわけではなく、ダウンロードするだけなので最悪 今のパフォーマンスでも駄目ということはないと 考えています。 ダウンロード時間は今のところ気にしていません。 保存できればOKと考えています。 > 1.1.8から 1.2.x に上げることはできません。 情報ありがとうございます。

すると、全ての回答が全文表示されます。
  • sasadora
  • ベストアンサー率68% (59/86)
回答No.3

>30万件でダウンロード開始まで50秒 とのことですが、これはどうやって調べたのでしょう? ブラウザでダウンロードダイアログが表示される時間だとすると、 ブラウザでダウンロード開始されるのは、 ダウンロード処理の部分がflushされてからかも知れません。 単純に1件目の処理が完了しただけでダウンロードが開始されるわけではないと思います。 ソース上の外側のrs.next()まで50秒かかるのだとしたら、もっとSQLの効率を上げるようにしたらよいと思います。(でも相当複雑なSQLなんでしょうね) どのぐらいのパフォーマンスを要求されているのか分からないのですが、20秒でダウンロード開始されればOKのレベルなんでしょうか? 普通に考えたら、20秒でも相当遅い気がするんですが…。 そうなると、インデックスを作成するなどのDB側の設計を直すために、実行計画を取得して検討するなど、Javaとは関係のないところでチューニングが必要だと思います。 SQL*plusではもっと開始が早いということなので、 ブラウザで確認した時間ではないですか? それならばもっと早い段階でブラウザへの出力をflushするようにすれば、ダウンロードの開始は早くなると思います。 ダウンロード処理は、どうやっていますか? Servletで、レスポンスヘッダを出力して、 それから出力を開始するというような感じでしょうか? だとしたら、レスポンスヘッダ出力後すぐにflushすれば、その後の検索処理がどれだけ時間がかかろうとも、すぐに保存のダイアログは表示されるはずです。

jkz
質問者

補足

>とのことですが、これはどうやって調べたのでしょう? ブラウザの目視確認でのダウンロード開始時間と、 下記のような計測で確認しています。両者の差はほとんど ないようです。 System.out.println("2" + setNowDate()); rs = stmt.executeQuery(); //...[1] System.out.println("2" + setNowDate()); > ソース上の外側のrs.next()まで50秒かかるのだとした> ら、もっとSQLの効率を上げるようにしたらよいと思いま> す。(でも相当複雑なSQLなんでしょうね) ご指摘のようにインデックスなどもありますが SQL plusで試行錯誤して早くなったクエリをJavaに載せると逆に遅くなってしまうことがあり、どのようにチューニングすべきかわからないのです。SQL plusとJava上での 違いや注意点など何かありますでしょうか? > Servletで、レスポンスヘッダを出力して、 > それから出力を開始するというような感じでしょうか? そうです。 検索前にレスポンスヘッダ出力する案はありますね。 結果が0件のときはヘッダだけ出力されますが、 どうしようもなければやむなしかもしれません。

すると、全ての回答が全文表示されます。
  • sasadora
  • ベストアンサー率68% (59/86)
回答No.2

やはりどういったSQLを実行しているかわからないと、 アドバイスされにくいと思います。 検索だけを実行しているのか、また検索を実行しながら、なにかしているのかを教えてもらわないと、 「遅いです」だけでは解答しようがないです。 30万件を一度に取得するわけではないと思いますが、 JDBC経由での大量に取得する検索のときに、 フェッチサイズを増やすことで格段にパフォーマンスが あがった経験があります。 #1件だけ取得するような処理だと効果はないと思います。 一度に取得する件数が膨大な事がわかっている場合には、 フェッチサイズを増やしてみて試してみてはどうでしょうか? JDBC2.0では標準で、Statement#setFetchSizeが使えますし、OracleでしたらOracle依存になってしまいますが、 Oracle プリフェッチ値の設定というのがありました。 詳しくはOTNのホームページからJDBC 開発者ガイドをダウンロードして見ると詳しく書いてあります。

参考URL:
http://otn.oracle.co.jp/document/products/oracle9i/index.html
jkz
質問者

補足

sasadoraさん、amajunさん、コメントありがとうございます。また情報不足ですみません。 補足します。 AIX4.3 Oracle version 8.0.5.1 Webshphere Application Server 3.0.2.2 JDK 1.18 です。 他のアプリケーションはなし > 検索だけを実行しているのか、 検索し、検索結果をブラウザからダウンロード しています。一度に取得するのは数件から三十万件くらい あるのです。1.18なので今試すことはできないのですが [質問]1.20に変えて試すことは簡単にできるものなのでしょうか。(別の質問になってすみません) このクラスのソースは八百行程ありますがここに載せられるでしょうか。概略書きます。 PreparedStatementを使用して。。。 executeQuery...[1] while ( rs.next() ) { executeQuery...[2] while ( rs.next() ) { クライアントへのデータのダウンロード処理 } } 一度に全ての集計をおこなうのではなく、ネストして executeQueryしています。これはダウンロードをできる だけ早く開始したいためです。 30万件でダウンロード開始まで50秒、ダウンロード 完了まで1時間位です。開始までをもっと早くしたい と考えています。 トレースして調べたところexecuteQuery...[1]がネックになっていました。 SQL plusでexecuteQuery...[1]と同じクエリを実行したときには20秒くらいで結果がでてきたのでもっと早くでるはずでは?と思いました。 と書きながら回答は難しいなあと思っています。 もちろんJAVAだけでなく仕様、ハード構成まで視野にいれて検討していますが、ここではJAVAについてコメントいただければと思います。 わかりにくくて申し訳ありませんが、何かアドバイスいただければ大変助かります。

すると、全ての回答が全文表示されます。
noname#30871
noname#30871
回答No.1

 コードを見ないとアドバイスは難しいです。  また、件数と処理時間の関係も。

すると、全ての回答が全文表示されます。

関連するQ&A