10

私はJava1.6、JTDS 1.2.2(1.2.4を試しただけで役に立たなかった)、SQL Server 2005を使用して、ストアドプロシージャ(パラメーターなし)を実行するためのCallableStatementを作成しています。同じストアドプロシージャを実行しているJavaラッパーがSQLServerManagement Studioを使用するよりも30%遅くなっています。私はMSSQLプロファイラーを実行しましたが、2つのプロセス間のI / Oにほとんど違いがないため、クエリプランのキャッシュに関連しているとは思いません。

ストアドプロシージャは引数をとらず、データを返しません。サーバー側カーソルを使用して、テーブルにデータを入力するために必要な値を計算します。

Javaからストアドプロシージャを呼び出すと30%のオーバーヘッドがどのように追加されるかわかりません。確かに、SQLが送信され、データベースがそれを実行するのはデータベースへのパイプにすぎません。データベースがJavaを提供している可能性があります。別のクエリプランをアプリしますか?

私はMSDNフォーラムとsourceforgeJTDSフォーラムの両方に投稿しました(トピック:「DBで直接よりもJTDSで遅いストアドプロシージャ」)これがなぜ起こるのかについて誰かが何か提案があるかどうか疑問に思いました。

前もって感謝します、

-ジェームズ

(NB恐れることはありません。解決策が見つかったら、他のフォーラムで得た回答をここでまとめます)

Javaコードスニペット:

sLogger.info("Preparing call...");
stmt = mCon.prepareCall("SP_WB200_POPULATE_TABLE_limited_rows");
sLogger.info("Call prepared.  Executing procedure...");
stmt.executeQuery();
sLogger.info("Procedure complete.");

SQLプロファイラーを実行しましたが、次のことがわかりました。

Javaアプリ:CPU:466,514読み取り:142,478,387書き込み:284,078期間:983,796

SSMS:CPU:466,973読み取り:142,440,401書き込み:280,244期間:769,851

(どちらもプロファイリングの前にDBCC DROPCLEANBUFFERSを実行し、両方とも正しい数の行を生成します)

だから私の結論は、彼らは両方とも同じ読み取りと書き込みを実行するということです、それは彼らがそれをしている方法が違うということです、皆さんはどう思いますか?

クエリプランはクライアントごとに大幅に異なることがわかります(Javaクライアントは、より高速なSQLクライアントにない挿入中にインデックスを更新します。また、結合の実行方法も異なります(ネストされたループとループ)。ストリームの収集、ネストされたループとインデックススキャン、argh!))。これがなぜなのか、私はまだわかりません(私がそれの底に達したときに私は再投稿します)

エピローグ

これを正しく動作させることができませんでした。JavaとMgmtスタジオクライアント間の接続プロパティ(など)を均質化してみarithabortました。ansi_nullsその結果、2つの異なるクライアントは非常に類似したクエリ/実行プランを持っていました(ただし、実際のplan_idは異なります)。JDBCクライアントと管理スタジオの間だけでなく、Microsoft独自のコマンドラインクライアントであるSQLCMDの間でもパフォーマンスが異なることがわかったので、MSDN SQL Serverフォーラムに見つけたものの要約を投稿しました。また、ネットワークトラフィックなどのより急進的なものもチェックしました。また、ニヤリと言うために、ストアドプロシージャを別のストアドプロシージャ内にラップします。

問題はカーソルの実行方法のどこかにあると感じています。それはどういうわけかJavaプロセスの中断を引き起こしていましたが、他に何も実行されていないときに別のクライアントがこの異なるロック/待機動作を引き起こす必要があるのはなぜですか。同じ実行計画が実行されているのは、私のスキルを少し超えています(私はDBAではありません!)。

その結果、このようなことを無駄にするのに4日で十分だと判断したので、それを惜しみなくコーディングします(正直なところ、ストアドプロシージャは、再コーディングではなく、より増分的に再コーディングする必要がありました。 -とにかく毎週すべてのデータを計算します)、そしてこれをチョークで書き留めて体験してください。質問を開いたままにしておきます。帽子をリングに入れてくれたすべての人に感謝します。それはすべて役に立ちました。誰かがさらに何かを思いついた場合は、さらにいくつかのオプションを聞きたいです...そして誰かが見つけた場合この投稿は、独自の環境でこの動作を確認した結果です。うまくいけば、ここにいくつかのヒントがあり、自分で試してみて、私たちよりも完全に確認できることを願っています。

週末の準備ができました!

-ジェームズ

4

8 に答える 8

4

プロファイラーをアタッチし、イベントSQL:BatchCompletedおよびSP:Completedを監視し、期間 > 1000 のフィルターを使用できます。 Java クライアントおよび SSMS から手順を実行します。2 つのイベントの読み取りと書き込みを比較します (Java と SSMS)。それらは大きく異なりますか?これは、実行パスまたはプランが大きく異なり、I/O に大きな違いがあることを示しています。

また、2 つのShowplan XMLイベントをキャプチャして、プランを比較してみてください (イベントを .sqlplan ファイルとして保存し、SSMS で開いて簡単に分析できるようにします)。彼らは同様の計画を持っていますか?見積もりと実際 (行、巻き戻し、再バインド) に大きな違いはありますか? それらは同じ程度の並列度を持っていますか? 計画は、sys.dm_exec_requestsビューから取得することもできます。

Missing Column StatisticsSort WarningsHash WarningExecution WarningsBlocked Processなどの警告イベントが発生しましたか?

要点は、調査ツールのすべての武器を自由に使用できるということです。違いの根本原因を見つけたら、Java 環境設定と SSMS 環境 (ADO.Net SqlClient) の違いを突き止めることができます。デフォルトのトランザクション分離レベル、ANSI 設定など。

于 2009-11-24T16:59:26.950 に答える
2

チェック: 2 つのアプリケーション (SSMS、Java) が SQL Server に対してまったく同じ呼び出しを行っており、SQL Server がそれぞれに対して異なる動作をしていることが問題ですか? もしそうなら、私はこのようなことを毎年、または 2 年に 1 回ぶつけて、何日も脳を痛めています。

一度、最終的に各プロセス呼び出しを分離し、プロファイラーでプロセス全体のすべてをログに記録しました。私は最終的に、Login イベント (TextData の下) が次のような多くの情報を示していることに気付きました。

-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

「Existing Connection」イベントにもこの情報が表示されますが、すぐに後続の呼び出し (バッチ、RPC、今は覚えていません) が送信され [ ISQL または OSQL がこれを行ったと思います]、これらの一部をすぐにリセットします -- Arithabort と Quoted_Identifier はお気に入りのようです。アプリケーションのデータベース インターフェイスが使用している接続プロトコルの設定や要件に応じて、他の SET オプションも変更されます。

もう 1 つ: 一部の設定は「作成」時にプロシージャの属性として保持され、その他の設定はコンパイル時に考慮されます。一方では、接続の SET 値が、プロシージャの作成時に保存された構成によって上書きされている可能性があります。一方、2 つの接続が大きく異なる場合は、1 つのプロシージャに対して 2 つの実行計画が生成されます。(この情報はすべて、十分な調査の後、sys. テーブルと DMV で入手できます。)

要するに、SQL の不明瞭さがあなたを混乱させているように思えます。今日まで、私はこれらすべての goombah 設定を嫌います。私の通知の下にあるものは、それらをいじり続けます[つまり、接続プールのimplicit_transactionを設定する愚か者は何ですか? しかし、彼らがやったら...] そして、地面 (ルール) があなたの下から変化し続けると、構造を構築するのは困難です. 結局のところ、沼地に城を建てることについてその男が言ったことを思い出してください...

于 2009-11-25T15:39:56.490 に答える
2

JTDS が文字列パラメーターを Unicode などに静かに変換していたため、少し前に同様の問題が発生したことを思い出します。その変換の結果、SQL Server は、SSMS からストアド プロシージャを実行したときに使用していたインデックスを使用できませんでした。

ハイ

于 2010-05-29T19:33:28.297 に答える
0

プロファイラーを見ていて、実行に違いがない場合、違いはクライアント システムにあるはずです。

送信するステートメントを準備するだけで 4 分間は長すぎるように思われるため、12 分間の待機は他の効果を引き起こすに違いありません。それが何であるかはわかりません。

于 2009-11-24T16:46:51.673 に答える
0

Java のケースには、Java サーバーへの結果の送信 (ネットワークのオーバーヘッド) と Java 処理が含まれますか? 12 分間のクエリで、大量のデータが生成される可能性があります。

于 2009-11-24T15:33:23.020 に答える
-1

申し訳ありませんが、私はこれに対する正しい答えを見つけられなかったので、これらのいずれも正しいとして割り当てたくないので、この答えを正しいとマークし、似たようなものに出くわした人に幸運を祈ります!

于 2010-02-11T17:53:38.420 に答える
-1

Microsoft がデータベース用の JDBC ドライバーを出荷していることをご存知ですか?

これらはよりパフォーマンスが高い場合があります。

明らかに..あなたは今までに問題を解決したかもしれません。

于 2010-04-22T20:16:16.103 に答える