空のテーブルをクエリするアプリケーション


10

私の会社では、かなり大きなパフォーマンスの問題があるアプリケーションを使用しています。データベース自体には多くの問題がありますが、私が取り組んでいるところですが、問題の多くは純粋にアプリケーションに関連しています。

私の調査では、空のテーブルをクエリする何百万ものクエリがSQL Serverデータベースにヒットしていることがわかりました。約300の空のテーブルがあり、それらのテーブルの一部は1分あたり最大100〜200回クエリされます。テーブルは私たちのビジネス領域とは何の関係もなく、基本的に元のアプリケーションの一部であり、ベンダーが私たちのためにソフトウェアソリューションを作成するように契約したときにベンダーが削除しませんでした。

アプリケーションエラーログがこの問題に関連するエラーであふれていると思われるという事実は別として、ベンダーは、アプリケーションまたはデータベースサーバーのいずれにもパフォーマンスまたは安定性の影響がないことを保証します。エラーログは、診断を行うために2分を超える価値のあるエラーが表示されない程度にフラッディングされます。

これらのクエリの実際のコストは、CPUサイクルなどの点で明らかに低くなります。しかし、SQL Serverとアプリケーションにどのような影響があるかを誰かが示唆できますか?リクエストの送信、確認、処理、返送、アプリケーションによる受信確認の実際のメカニズム自体がパフォーマンスに影響を与えると思います。

アプリにはSQL Server 2008 R2、Oracle Weblogic 11gを使用しています。

@ Frisbee-短い話ですが、アプリのデータベースの空のテーブルにヒットするクエリテキストを含むテーブルを作成し、空であることがわかっているすべてのテーブル名についてクエリを実行し、非常に長いリストを取得しました。トップヒットは30日間の稼働時間で270万回の実行でした。アプリは一般的に午前8時から午後6時まで使用されているため、これらの数値は運用時間に集中しています。複数のテーブル、複数のクエリ、おそらく結合を介した関連性の高いものとそうでないもの。トップヒット(当時は270万)は、結合のないwhere句を使用した単一の空のテーブルからの単純な選択でした。空のテーブルへの結合を伴うより大きなクエリにはリンクテーブルの更新が含まれる可能性があると予想しますが、それを確認してこの質問をできるだけ早く更新します。

更新:1043から4622614(2.5か月以上)の実行数のクエリが1000個あります。キャッシュされたプランがいつから始まったかを調べるために、さらに掘り下げる必要があります。これは、クエリの範囲を把握するためのものです。ほとんどは、20を超える結合でかなり複雑です。

@ srutzky-はい、計画がいつコンパイルされたかに関連する日付列があると思いますので、それを確認してみましょう。SQL ServerがVMwareクラスター上にある場合、スレッドの制限が要因になるのでしょうか。ありがたいことに、すぐに専用のDell PE 730xDになります。

@Frisbee-返信が遅くなってすみません。あなたが示唆したように、SQLQueryStress(実際には240,000回の反復)を使用して、空のテーブルからselect *を24スレッドで10,000回実行し、10,000バッチリクエスト/秒をすぐにヒットしました。その後、24スレッドで1000倍に削減し、4,000バッチリクエスト/秒未満でヒットしました。また、12スレッドのみで10,000回の反復を試行し(合計120000回の反復)、これにより、持続的な6,505バッチ/秒が生成されました。CPUへの影響は実際に顕著で、各テスト実行中の合計CPU使用量の約5〜10%です。ネットワーク待機はごくわずかでした(私のワークステーション上のクライアントで3ミリ秒など)が、CPUへの影響は確かにありました。それは、CPU使用率と、不要なデータベースファイルIOに要約されます。1秒あたりの合計実行回数は3000弱で計算され、これは本番環境ではありませんが、このような数十のクエリの1つだけをテストしています。したがって、毎分300〜4000回の割合で空のテーブルにヒットする何百ものクエリの正味の影響は、CPU時間に関しては無視できません。すべてのテストは、デュアルフラッシュアレイと256GB RAM、12個の最新コアを備えたアイドル状態のPE 730xDに対して行われました。 これはSQLSentryからの出力です

@ srutzky-良い考え。SQLQueryStressはデフォルトで接続プールを使用しているようですが、とにかく調べてみたところ、接続プールのボックスがオンになっていることがわかりました。フォローして更新

@ srutzky-アプリケーションで接続プーリングが有効になっていないようです-有効になっている場合は機能していません。プロファイラートレースを実行したところ、接続に監査ログインイベント用のEventSubClass "1-Nonpooled"があることがわかりました。

RE:接続プーリング-weblogicsをチェックしたところ、有効な接続プーリングが見つかりました。プーリングのトレースをさらに実行し、プーリングの兆候が正しく/まったく発生していないことを発見しました: ここに画像の説明を入力してください

次に、データが設定されたテーブルに対して結合を使用せずに単一のクエリを実行すると、次のようになります。例外は、「SQL Serverへの接続の確立中にネットワーク関連またはインスタンス固有のエラーが発生しました。サーバーが見つからなかったか、アクセスできませんでした。インスタンス名が正しく、SQL Serverがリモート接続を許可するように構成されていることを確認してください。 (プロバイダー:名前付きパイププロバイダー、エラー:40-SQL Serverへの接続を開けませんでした) "バッチリクエストカウンターに注意してください。例外が生成されている間にサーバーにpingを実行すると、ping応答が成功します。

ここに画像の説明を入力してください

更新-2つの連続するテスト実行、同じワークロード(select * fromEmptyTable)、プーリング有効/無効。CPU使用率がやや多く、多くの障害が発生し、500バッチリクエスト/秒を超えることはありません。テストでは、10,000バッチ/秒でプールがオンの場合の障害はなく、約400バッチ/秒の場合、プールが無効になっているために多くの障害が発生しています。これらの失敗は接続の可用性の欠如に関連しているのだろうか?

ここに画像の説明を入力してください

@ srutzky- sys.dm_exec_connectionsからCount(*)を選択します。

  • プーリングが有効:負荷テストが停止した後でも37が一貫して

  • 無効化されたプーリング:
    SQLQueryStressで例外が発生しているかどうかに応じて11-37。つまり、これらの谷がBatches
    / secグラフに表示されると、SQLQueryStressで例外が発生し
    、接続数が11に減少し、その後37に徐々に戻ります。バッチがピークに達し、例外が発生していないとき。とても面白いです

デフォルトの0に設定されている両方のテスト/ライブインスタンスの最大接続数。

アプリケーションログを確認しても接続の問題は見つかりませんが、エラーの数とサイズが多いため、利用できるログ記録は数分しかありません。つまり、スタックトレースエラーがたくさんあります。アプリサポートの同僚は、接続に関連してかなりの数のHTTPエラーが発生するとアドバイスしています。これは、何らかの理由でアプリケーションが正しく接続をプールしておらず、その結果、サーバーが繰り返し接続を使い果たしているように思われます。アプリのログを詳しく調べます。これがSQL Server側からの運用で起こっていることを証明する方法はあるのでしょうか。

@ srutzky-ありがとうございます。明日weblogicの設定を確認して更新します。たった37の接続について考えていましたが、SQLQueryStressが12のスレッドを10,000回の反復で実行している場合= 120,000の選択ステートメントがプールされていない場合、各選択がSQLインスタンスへの個別の接続を作成することを意味しませんか?

@ srutzky- Weblogicは接続をプールするように構成されているため、正常に機能しているはずです。接続プーリングは、4つの負荷分散された各Weblogicで次のように構成されます。

  • 初期容量:10
  • 最大収容人数:50
  • 最小容量:5

空のテーブルからの選択クエリを実行するスレッドの数を増やすと、接続数は最大で約47になります。接続プーリングが無効になっていると、毎秒の最大バッチ要求が常に低くなっています(10,000から約400に)。毎回発生するのは、SQLQueryStressの「例外」が、バッチ/秒が谷に入った直後に発生することです。これは接続性に関連していますが、なぜこれが起こっているのか正確には理解できません。テストが実行されていない場合、#connectionsは約12に下がります。

接続プーリングが無効になっていると、例外が発生する理由を理解できませんが、それがAdam Machanicに対する他のstackExchange質問/質問である可能性がありますか?

@srutzky SQL Serverの接続が不足していなくても、プーリングを有効にせずに例外が発生するのはなぜでしょうか。


1
Peter、接続プーリングに関する最新の更新を念頭に置いて、SQLQueryStressを使用してテストを再実行する必要があるようですが、接続プーリングはオフになっています。これは、アプリの動作の影響をより正確に反映したものであり、CPU使用率とRAM使用率の増加さえ示すと思います。
ソロモンルツキー2016年

1
ピーター、サーバーに設定された接続の最大数はありますか?プーリングなしでは、接続が多すぎるという問題が発生していると思います。アプリでこのエラーが発生することはないでしょうか。また、これらの2つの構成のそれぞれに対してテストが実行されている間に、最後のテストをもう一度(プールが有効な場合とない場合の両方で)再実行できるSELECT COUNT(*) FROM sys.dm_exec_connections;場合は、a を実行して、プールが有効な場合と無効な場合で値が大きく異なるかどうかを確認しますない。これらのエラーに基づいて、プーリングが無効になっている場合、接続はさらに多くなると思います。
ソロモンルツキー16年

1
ピーター、37人の接続は、ひどく低い最大値のようです。接続制限が0(つまり無制限)に設定されている場合、システムメモリはバインドされていますか?また、接続プールはデフォルトでオンになっているはずですが、クライアントによって制御されます。アプリは.NETアプリですか?接続プーリングを使用するためにある必要はありませんが、これの原因を見つけるために知るのに役立ちます。また、使用されている接続文字列を確認できますか?それを指定していますPooling=falseMax Pool Size
ソロモンルツキー2016年

1
ピーター、12のスレッドのそれぞれが、クエリごとに独自の接続を作成しています。したがって、プールしないと、コードが接続を閉じるとすぐに接続を破棄できます。プーリングは、再利用のために接続を維持します。したがって、プーリングを使用している間、接続の数は一定でした。37の詳細情報がない理由がわかりません。テストが実行されていない場合、接続はいくつありますか?その数を取り消すと、テストによって作成された数がわかりやすくなります。
ソロモンルツキー2016年

1
接続プーリングは、サーバーではなくクライアントごとに維持されます。したがって、WebLogicとSQLQueryStressはそれぞれ独自の接続プールを持つ必要があります(min_poolやmax_poolサイズなどに関して)。「接続プーリングが無効になっていると、最大バッチリクエスト数/秒が低くなります」:アプリからの接続ごとにセッションの認証と初期化に時間がかかるため、これは理にかなっています。これがまさに接続プーリングが存在する理由です。 )。
ソロモンルツキー2016年

回答:


7

リクエストの送信、確認、処理、返送、アプリケーションによる受信確認の実際の仕組み自体がパフォーマンスに影響を与えると思います。

はい、さらにいくつかの追加の要因がありますが、これらのいずれかが実際にシステムに影響を与えている程度は、システムを分析せずに言うことは不可能です。

そうは言っても、あなたは何問題であるのかを尋ねています、そしてそれらのいくつかが現在あなたの特定の状況の要因ではないとしても、言及すべきことがいくつかあります。あなたはそれを言う:

約300の空のテーブルがあり、それらのテーブルの一部は1分あたり最大100〜200回クエリされます。

  • クエリされていない空のテーブルは問題になりません。しかし、あなたはそれらがすべて照会されていることを意味しているのかもしれません。
  • 送信されるクエリテキストが呼び出し間で同じままであれば、クエリの解析と実行プランの生成はそれほど問題にはなりません。SQL Serverはクエリのテキストをハッシュし、プランキャッシュで検索します。見つかった場合は、解析またはコンパイルのいずれの手順も実行されません(プランがキャッシュから削除されるまで)。
  • 空または空でないテーブルでは、リソースが使用されていることを示すために、少なくとも「共有」ロックが必要です。これにより、リソースの使用中に、排他ロックを必要とする操作(列の追加/変更/削除など)が変更を行うことを防ぎます。データがないために1ミリ秒未満で完了したとしても、ロックとロック解除には、それらのロック操作を管理するためのシステムリソース(メモリとCPU)が必要です。
  • SQL Serverからアプリに返される結果セットがない場合でも、クエリが結果を生成するかどうかにかかわらず、SQL Serverに送信されるネットワークトラフィックの量は同じです。クエリのテキストまたはストアドプロシージャの名前を送信する必要があります。結果が返されない場合でも、SQL Serverは、結果セットが開始されていることをクライアントに通知し(行が見つからない場合でも)、結果セットが終了し、閉じる必要があります。また、printステートメントや行カウントからの追加メッセージが存在する可能性があります。
  • SQL Serverに接続するには、ある程度のシステムリソースが必要です。認証(およびネットワークパケットのやり取り)を処理するには、CPUとメモリが必要です。これにも時間がかかります。これが、接続プールが存在する理由です。この費用を削減するためです。
  • 接続プールがシステムリソースの使用量を減らしても、SQL Serverはそれらの接続を維持する必要があり、メモリと最小限のCPUが必要です。
  • 行がなく、実行時間が非常に短い場合でも、クエリは実行されました。10行または10,000行があり、それらが頻繁に使用されたためにそれらがバッファープール(つまりメモリ)からプルされた場合でも、スレッドはその処理を実行する必要があります。そして、この役に立たないクエリを処理しているスレッドは、実際に役立つクエリを処理していません

もっともっとあるかもしれませんが、これは物事の感覚を得るために役立つはずです。また、ほとんどのパフォーマンスの問題と同様に、それはすべて規模の問題であることを覚えておいてください。上記のすべてのアイテムは、1分に1回ヒットした場合は問題になりません。これは、ワークステーションまたは開発データベースで変更をテストするようなものです。常に、テーブル内の10〜100行だけで機能します。そのコードを本番環境に移行すると、実行に10分かかり、誰かが「まあ、それは私のボックスで動作します」と言わざるを得ません;-)。つまり、問題が発生しているのは、発信された通話の量が多いためだけですが、それは存在する状況です。

したがって、100万の役に立たない、0行のクエリであっても、次のようになります。

  • 追加の200万のロック操作(すべてのロックはロック解除する必要がありますよね?)これは主に、有用な操作ではなく、無駄な操作に費やされる時間のコストです。
  • 飽和状態に近づく可能性のあるより多くのネットワークトラフィック(これがどれほど可能性があるかはわかりませんが、それでも)
  • より多くのメモリを消費する接続が維持されています。未使用の物理RAMはどれくらいありますか?そのメモリは、クエリやクエリプランキャッシュを実行するために適切に使用されます。最悪の場合、物理メモリが不足し、SQL Serverが仮想メモリ(スワップ)の使用を開始する必要があるため、処理が遅くなります(ページングされているメモリに関するメッセージが表示されていないか、SQL Serverエラーログを確認してください)。

    そして、誰かが「まあ、接続プーリングがある」と言っている場合に備えて。はい、それは間違いなく必要な接続の数を減らすのに役立ちます。ただし、クエリは1分あたり最大200回受信されるため、これは多くの同時アクティビティであり、正当な要求のために接続が存在する必要があります。a SELECT * FROM sys.dm_exec_connections;を実行して、維持しているアクティブな接続の数を確認します。

  • 何に関係なく、これは1日の間に少なくとも100万回であり、有用な何かをしている可能性のあるスレッドが代わりに利用できなかったということです。

私がここで述べていることについて私が間違っていない場合、たとえ小規模であっても、ネットワークとSQL Serverに偽の要求が殺到しているため、これはシステムに対する一種のDDoS攻撃であると思われます、実際のリクエストがSQL Serverに到達したり、SQL Serverによって処理されたりすることを防ぎます。


1

テーブルが1分間に100〜200回ヒットする場合、それらは(うまくいけば)メモリ内にあります。サーバーの負荷は非常に低いです。データベースサーバーに高いCPUまたはメモリがない限り、これはおそらく問題ではありません。

はい、クエリは共有ロックを取得しますが、うまくいけば、更新ロックをブロックしたり、更新ロックによってブロックされたりすることはありません。これらのテーブルの更新、挿入、削除はありますか?そうでなければ、私はそれを手放します-あなたがパフォーマンスの問題を抱えているなら、データベースサーバーの観点から、より大きな魚がフライする必要があります。

空のテーブルで100,000の選択カウント(*)でテストを実行しましたが、32秒で実行され、クエリはネットワーク経由で行われました。つまり、1/3ミリ秒です。ネットワークが過負荷にならない限り、これはクライアントに影響を与えることさえありません。パフォーマンスに大きな問題がある場合、これらの1/3ミリ秒の空のクエリはアプリを強制終了するものではありません。

そして、これらは現在のアプリケーションの一部ではないいくつかの静的型データを取得する左結合の一部である可能性があります。他のクエリと連鎖させることができるので、余分な往復ではありません。もしそうなら、それはずさんですが、それ以上のトラフィックを引き起こしていません。

それでは、実際のステートメントをもう一度見てみましょう。これらのテーブルの更新、追加、削除はありますか?

はい、多くの空のテーブルと空のテーブルへのクエリは、ずさんなコーディングを示しています。しかし、大きなパフォーマンスの問題が発生している場合、これらのテーブルで実際にずさんな書き込み操作が行われていない限り、これは原因ではありません。


10万回のクエリテストを実行したときに、SQL Serverでクエリを実行していたユーザーは他に何人いましたか?私が正しいと言っているのではなく、あなたが間違っているとは言えませんが、あなたがシステム上で1人しかいない場合、または数人のうちの1人であれば、当然、それほど大きな影響はありません。ロックの問題はブロックの問題ではなく、データが常にバッファプールにある場合でも、SQL Serverがそれらのデータページをロックおよびロック解除するために必要なリソースの問題でした。それはまだ行われている仕事です。そして、スケジューラは無制限ではありません。
ソロモンルツキー

そして、私はあなたが間違っていると言っているのではありません。他のユーザーであろうとなかろうと、それは、それがかかった時間とリソースの測定の有効な尺度です。30秒で1つのクライアントから100,000は、その負荷を200から400倍超過します。更新ロックがない場合、1つのクライアントから来たか、100から来たかは、違いはありません。あなたの答えは、過負荷のネットワークまたはSQLサーバーのいずれかがあり、あなたが知らない質問に基づいていることを前提としています。これがDDoS攻撃である場合、100 /秒(分ではなく)になり、空のテーブルに対するものではありません。
パパラッツォ

正解です。問題を絞り込むのに十分な知識がありません。そのため、状況によってこれらの問題が問題になる可能性があると私は言っていました。そして、DDoSの問題は単なるアナロジーであり、主に元の質問の文言に基づいており、そのレートでいくつかがヒットし、他の多くもヒットすることをほのめかしていましたが、頻度はわずかです。
ソロモンRutzky

これは、最初の段落で非常によく要約されているという意味で、貴重な回答だと思います。「データベースサーバーに高いCPUまたはメモリがない限り、これはおそらく問題ではありません。」私たちのケースでは、1日の特定の時間にCPU使用率が高いため、追加のCPU圧力は、私のテストに基づく要因のようです。
Peter

特に、実際にはこれらの空のテーブルに対して約50のクエリがあり、実行数が200〜4000 /分である場合、100〜200回/分を実行するクエリのみを引用しました。累積的に、この頻度で空のテーブルをクエリする効果は、パラメーター化されていないクエリが繰り返し実行される最良のシナリオでも、CPUに大きな影響を与えるため、プラン、データなどはすべてメモリ内にあります。
Peter

0

一般に、各クエリでは次の手順が実行されます。

  1. アプリケーションからのリクエスト。
  2. データベースクエリを解析します。
  3. データベースエンジンは、このクエリが既にRAMに格納されているかどうかを確認します。メモリに存在する場合は実行プランを使用します。
  4. RAMに存在しない場合、データベースエンジンはクエリ内のオブジェクトの既存の統計をチェックし、実行プランを決定します。
  5. 実行プランを実行し、I / Oを使用してディスクからデータを取得します。
  6. アプリケーションへの応答。

あなたが述べたように多くのクエリは、すでに重いシステムに余分な負荷をかけるかもしれません-接続、CPU、RAM、I / Oへの余分な負荷。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.