Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 >  掲示板 >  掲示板(更新処理が極端に「遅い」データがあります。)
閲覧数:2352
掲示板(更新処理が極端に「遅い」データがあります。)
名前
匿名
題名 更新処理が極端に「遅い」データがあります。
質問内容

質問を評価する
(0ポイント)
以下の事象について、心当たりのある方がいらっしゃいましたらご協力お願いします。
説明がかなり中度半端で申し訳ございません。
(事象がはっきりしているのでが、原因が全く分からずつかめないのです)

≪事象≫
・JAVAシステムにて、画面よりAデータに対して更新を行うと極端に「遅い」。
 →変更せず、更新だけ行いました
・しかし、Bデータに対して更新を行うと「早い」。
 →Aデータとの情報量にほどんど差はない
・更新先は、1テーブル1レコード。
・何度やっても結果は同じ。
・デバッグで、SQLに時間がかかっているのはわかるが・・・。
・別処理での検索でも「遅い」。

≪試してみたこと≫
・AデータとBデータのkey項目以外を入れ替えても、Aデータが必ず「遅い」。
・Aデータに紐付いているデータ(マスタ以外)をdeleteしても、必ず「遅い」。
・処理時間がかかっているSQLを抜き出して、単体で処理を行うと「遅く」ない。


≪環境≫
DB:SQLServer2008 R2
開発言語:JAVA
開発環境:eclipse3.3.2


現象はこんなにはっきりしているのでが、どうにもならない状況です。
ぜひとも、ご協力お願いいたします。

以上
質問日時 2013-01-25 17:06:09
名前
匿名
回答内容

回答を評価する
(0ポイント)
JDBCドライバ絡みの問題っぽいなー。

と思って検索してみると、こんなのが見つかった。

http://social.msdn.microsoft.com/Forums/ja/sqlserverja/thread/
d0e9816a-4a76-49ff-898b-f2259b3b5089
回答日時 2013-01-25 18:37:31
名前
匿名
回答内容

回答を評価する
(0ポイント)
ご回答ありがとうございます。

現象は一致しているので、「WHERE句のコードをUnicodeコードで検索に行っていたのを、ASCIIコードで行くように変更したところ、レスポンスがよくなりました」で解決できそうです。

そこで、さらに質問させてください。
「WHERE句のコードをUnicodeコードで検索に行っていたのを、ASCIIコードで行くように変更」するには、どのようにしたらよいのですか。

調べているのですが、DBに設定するのか、SQL文で変換させるのかすら分かりません。

ぜひともご教授お願いします。
回答日時 2013-01-28 13:21:38
名前
匿名
回答内容

回答を評価する
(0ポイント)
環境ないから全く試してない。

http://otndnld.oracle.co.jp/document/products/wlevs/docs30/jd
bc_drivers/mssqlserver.html
回答日時 2013-01-29 00:10:30
名前
匿名
回答内容

回答を評価する
(0ポイント)
ご回答ありがとうございました。
設定方法はわかりましたが、以下の問題があり、再度質問させてください。

【問題】
当方の検索対象テーブルには、nvarchar項目(氏名)があり、unicode範囲の外字も使用しています。
 この場合、「SendStringParametersAsUnicode」を『false』にすると文字化けに繋がり心配です。


ズバリ、この現象はどんな場合に発生するのですか?
(ネットで調べても原因までは書かれていなかったので・・・)
単純に考えるとどこでも発生しえるバグのような気がします。
となると、別の回避方法があるのではと思って仕方がありません。
(例えば、全体設定ではなく、項目単位の設定。JAVA側での対応等)

もし、別の回避方法があればご教授お願いします。

身勝手だと思いますが、この回避方法は納得できません。(泣)


回答日時 2013-01-29 10:09:22
名前
匿名
回答内容

回答を評価する
(0ポイント)
DB製品によりまちまちですが、PrepareStatementを使用して発行したクエリは
単純なSQLとして実行されないことがほとんどです。
SQL Serverの場合は、sp_executesqlプロシジャとして実行されるようです。

【参考】http://www.isla-plata.org/wiki/pukiwiki.php?
SQLServer%20JDBC%A5%C9%A5%E9%A5%A4%A5%D0%A4%C8SendStringParametersAsUnicode%A5%AA%A5%D7%A5%B7%A5
%E7%A5%F3

スレ主さんが「単体で試した場合に速い」としているのは、
Javaコード中に"select * from tbl where key = ?"と記述したクエリの
プレースホルダ('?')をリテラル値に書き換えて実行したのではないでしょうか?

なんとなく話の流れからするとSQLServer側のsp_executesqlプロシジャで
パフォーマンス劣化するケースがあり、JDBCドライバがそれに該当するケースに
変換してクエリ発行しているような気がします。

パフォーマンスチューニングとしては実際に発行されたクエリで検証するのが
常道ですので、まずはSQL Server側へ発行している実際のクエリを調査し、
クエリ単体で実行した場合でも同じ遅さが再現できるかを確認されるのがよろしいか
と思います。
(SQL Serverは詳しくないのですがDB管理ツール等でクエリトレースを見てみるとか)

あと、最終手段として速度劣化が気になる部分についてはPrepareStatementを
使用しないという手もあります。
(もちろん自前でSQLインジェクション対応が必要になりますが)
回答日時 2013-01-29 12:21:54
名前
匿名
回答内容

回答を評価する
(0ポイント)
ご回答ありがとうございます。

>スレ主さんが「単体で試した場合に速い」としているのは、
>Javaコード中に"select * from tbl where key = ?"と記述したクエリの
>プレースホルダ('?')をリテラル値に書き換えて実行したのではないでしょうか?

そうです。


状況が少し進んだのでお知らせします。
・JAVAに、SQLServerの接続オプション「SendStringParametersAsUnicode」を『false』としたら、遅延が解消されました。(それ以外は触っていません)
・ただし、unicodeの外字(私用領域)で検索すると、検索結果の外字部分が文字化けする。
 →画面への入力時は、正常に表示されます。
 →更新すると、外字が文字化け『?』となる。
 →テーブルに登録されている内容も『?』。
 →検索画面で、外字で検索すると検索される。
  ただし、表示は『?』


結果、
JDBCドライバがパラメータクエリで使われる文字列パラメータをUnicodeに変換する際に問題がありそうです。
現象は確認できたのですが、原因・対応策はわかりません。

SQLServer2008 R2(RTM)に、SP2をあててみようと思います。
というか、これってバグじゃないんですかね〜(泣)
回答日時 2013-01-30 15:11:48
名前
匿名
回答内容

回答を評価する
(0ポイント)
スレ主です。

SQLServer2008 R2(RTM)にSP2等をあてて最新状態にし絵も状況は同じでした。
また、JDBCを4.0にしても状況は同じでした。

現象がはっきりしてるだけにくやしいです(泣)。

どなたか、助けてくださいm(__)m
回答日時 2013-02-01 10:57:03
名前
匿名
回答内容

回答を評価する
(0ポイント)
StringではなくBinaryStreamでやり取りしてみる。
また例によって全く試さずに言ってるけど。
回答日時 2013-02-01 21:00:51
名前
匿名
回答内容

回答を評価する
(0ポイント)
スレ主です。

ご回答ありがとうございました。

>StringではなくBinaryStreamでやり取りしてみる。
>また例によって全く試さずに言ってるけど。

update文でgetbytesを使ったんですが、
文字化けしてしまいました。
ただし、トレースすると変数が『@varchar』ではなく『@varbinary』になっていました。
(これはちと進展しましたか?)

なかなか状況が好転しないのですが、SQLServerの接続オプション「SendStringParametersAsUnicode」を『false』としたら、
・Select文では、外字(unicode)が含まれていても正しく表示される。
・Update文では、外字(unicode)が含まれていたら、その文字が『?』となる。テーブルの内容も『?』。

今、挑戦しようとしてるのは「setNStirng」です。
トレース時のパラメータのタイプを『@Nvarchar』に出来れば、なんとかなりそうです。
が、「setNString」って、
 setNString(int,string)
はダメなんですか?
使えそうなのですが、プログラムで、
『メソッドsetNString(int,String)は型PreparedStatementで未定義です。』と帰ってきます。

PreparedStatementクラスで使えるとあるのですが、何が間違っているかご教授いただけないでしょうか。

皆様、いろいろとご協力ありがとうございます。
回答日時 2013-02-04 17:01:15

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。



このページのトップへ
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道_CopyrightJavaの道