複数のデータベース呼び出しは、Web APIのネットワーク呼び出しでは本当に重要ですか?


16

私の雇用主の1人で、REST(しかしSOAPにも適用されます)APIに取り組みました。クライアント(アプリケーションUI)は、API(Web(一般的な運用展開ではLAN)経由で)を呼び出します。APIはデータベースを呼び出します。

私たちの議論で繰り返されるテーマの1つはパフォーマンスです。チームの一部の人々は、パフォーマンスのために1つのAPI呼び出しから複数のデータベース呼び出し(通常は読み取り)を行うべきではないと考えています。各API呼び出しが(正確に)データベース呼び出しを1つだけ持つように最適化する必要があります。

しかし、それは本当に重要ですか?UIはAPIに対してネットワーク呼び出しを行う必要があることを考慮してください。それはかなり大きいです(ミリ秒単位)。データベースは、メモリ内に物事を保持し、読み取りを非常に迅速に実行するように最適化されています(たとえば、SQL ServerはすべてをRAMにロードして保持し、可能な限りすべての空きRAMを消費します)。

TLDR:すでにLAN経由でネットワーク呼び出しを行っているときに、複数のデータベース呼び出しを心配することは本当に重要ですか?もしそうなら、なぜですか?

明確にするために、私は大きさについて話しています-それは仕様(マシンハードウェア、APIとDBの選択など)に依存することを知っています桁違いに少ない呼び出し、実際に問題ですか?それとも、これ以上の問題がありますか?

編集:後世のために、これらの状況下でデータベース呼び出しを組み合わせてパフォーマンスを改善する必要があると主張するのは非常にばかげていると思います-特にプロファイリングがない場合。ただし、これを行うかどうかは私の判断ではありません。これがWeb API呼び出しを最適化する正しい方法であると考える背後にある根拠を知りたいです。


APIレイヤーとデータベースの間に別のネットワーク呼び出しはありませんか?
サイン

4
タイミングテストは何を示しましたか?
ダンピチェルマン14

@Sign APIとDBの間にネットワーク呼び出しはありません。私が理解していることから、それらは同じマシン上にあることが保証されています。
ashes999 14

@DanPichelmanそれも私が求めていることです。誰もパフォーマンスを取ってタイミングを計っていないようです。「すべてのDB呼び出しを単一の呼び出しに結合することにより、Xのパフォーマンスを修正する」という要件が得られます。
ashes999 14

回答:


25

しかし、それは本当に重要ですか?UIはAPIに対してネットワーク呼び出しを行う必要があることを考慮してください。それはかなり大きいです(ミリ秒単位)。データベースは、メモリ内に物事を保持し、読み取りを非常に迅速に実行するように最適化されています(たとえば、SQL ServerはすべてをRAMにロードして保持し、可能な限りすべての空きRAMを消費します)。

ロジック

理論的には、あなたは正しいです。ただし、この理論的根拠にはいくつかの欠陥があります。

  1. あなたが述べたことから、実際にアプリをテスト/プロファイリングしたかどうかは不明です。言い換えれば、アプリからAPIへのネットワーク転送が最も遅いコンポーネントであることを実際に知っていますか?それは直感的であるため、そうであると推測するのは簡単です。ただし、パフォーマンスについて議論するときは、決して想定すべきではありません。私の雇用主では、私がパフォーマンスのリーダーです。私が最初に参加したとき、人々は、ボトルネックが何であるかについての直感に基づいて、CDN、複製などについて話し続けました。結局のところ、パフォーマンスに関する最大の問題は、パフォーマンスの低いデータベースクエリでした。

  2. データベースはデータの取得に優れているため、データベースは必然的に最高のパフォーマンスで実行され、最適に使用されており、それを改善するためにできることは何もないと言っています。つまり、データベースは高速になるように設計されているため、心配する必要はありません。別の危険な考え方。それは、車は速く動くことを意図しているので、オイルを交換する必要はないということです。

  3. この考え方は、一度に1つのプロセスを想定するか、別の言い方をすれば、並行性を前提とはしていません。1つの要求が別の要求のパフォーマンスに影響を与えないことを前提としています。ディスクI / O、ネットワーク帯域幅、接続プール、メモリ、CPUサイクルなどのリソースは共有されます。したがって、1つのデータベース呼び出しの共有リソースの使用を減らすことで、他のリクエストの速度低下を防ぐことができます。私が現在の雇用主に最初に参加したとき、経営者は3秒のデータベースクエリの調整は時間の無駄であると考えていました。3秒はとても短いのに、なぜ時間を無駄にしますか?CDNや圧縮などを使用した方が良いと思いませんか?しかし、インデックスを追加することで、3秒のクエリを1秒で実行できるようにすると、ブロックが2/3減り、スレッドを占有する時間が2/3減り、さらに重要なことに、ディスクから読み取られるデータが減ります。

法則

ソフトウェアのパフォーマンスは単に速度に関するものであるという一般的な概念があります。

純粋に速度の観点からすると、あなたは正しいです。システムの速度は、最も遅いコンポーネントと同じです。コードのプロファイルを作成し、インターネットが最も遅いコンポーネントであることがわかった場合、他のすべては明らかに最も遅い部分ではありません。

ただし、上記を考慮すると、リソースの競合、インデックス作成の欠如、コードの記述不足などにより、パフォーマンスに驚くべき違いがどのように発生するかを理解できると思います。

仮定

最後に一つだけ。データベースコールは、アプリからAPIへのネットワークコールと比較して安価であるべきだと述べました。しかし、アプリとAPIサーバーは同じLANにあることも言及しました。したがって、どちらもネットワークコールと同等ではありませんか?言い換えると、両方が同じ利用可能な帯域幅を持っている場合、API転送がデータベース転送よりも桁違いに遅いと仮定するのはなぜですか?もちろん、プロトコルとデータ構造は異なりますが、私はそれを得ますが、それらが桁違いに異なるという仮定に異議を唱えます。

それが濁った場所

この質問全体は、「複数」対「単一」のデータベース呼び出しに関するものです。しかし、いくつが複数であるかは不明です。上記のことから、一般的な経験則として、必要なデータベース呼び出しはできるだけ少なくすることをお勧めします。しかし、それは経験則にすぎません。

その理由は次のとおりです。

  1. データベースはデータの読み取りに優れています。それらはストレージエンジンです。ただし、ビジネスロジックはアプリケーション内に存在します。すべてのAPI呼び出しの結果、データベース呼び出しが1つだけになるというルールを作成すると、ビジネスロジックがデータベースで終了する可能性があります。たぶんそれは大丈夫です。多くのシステムがそうしています。しかし、そうでない人もいます。それは柔軟性についてです。
  2. 時々、適切な分離を実現するために、2つのデータベース呼び出しを分離したいことがあります。たとえば、すべてのHTTP要求は、ユーザーが適切なアクセス権を持っていることをDBから検証する汎用セキュリティフィルターを介してルーティングされる可能性があります。該当する場合は、そのURLに適切な機能を実行します。その関数はデータベースと対話する場合があります。
  3. ループでデータベースを呼び出します。これが、何が複数かを尋ねた理由です。上記の例では、2つのデータベース呼び出しがあります。2は大丈夫です。3は大丈夫です。Nはうまくありません。データベースをループで呼び出す場合、パフォーマンスは線形になりました。つまり、ループの入力にあるほど時間がかかります。APIネットワーク時間が最も遅いと断定的に言うと、データベースを10,000回呼び出す未発見のループが原因で長時間かかっているトラフィックの1%のような異常を見落とします。
  4. 複雑な計算のように、アプリが得意なこともあります。データベースからデータを読み取って計算を行い、その結果に基づいて、2番目のデータベース呼び出しにパラメーターを渡す必要がある場合があります(結果を書き込む場合があります)。データベースを1回だけ呼び出すためだけに、これらを単一の呼び出し(ストアドプロシージャなど)に結合すると、アプリサーバーが得意とする可能性のあるものにデータベースを使用せざるを得なくなります。
  5. 負荷分散:1つのデータベース(おそらく)と複数の負荷分散アプリケーションサーバーがあります。そのため、アプリがより多くの作業を行い、データベースが少ないほど、一般にデータベースの複製をセットアップするよりもアプリサーバーを追加する方が簡単であるため、スケーリングが容易になります。前の箇条書きに基づいて、SQLクエリを実行してから、複数のサーバーに分散されているアプリケーションですべての計算を実行し、終了時に結果を書き込むことは理にかなっています。これにより、スループットが向上します(全体のトランザクション時間が同じ場合でも)。

TL; DR

TLDR:すでにLAN経由でネットワーク呼び出しを行っているときに、複数のデータベース呼び出しを心配することは本当に重要ですか?もしそうなら、なぜですか?

はい。ただし、ある程度までです。実用的な場合はデータベース呼び出しの数を最小限に抑えるようにしますが、それらを結合するためだけに互いに関係のない呼び出しを結合しないでください。また、ループ内でデータベースを呼び出すことは避けてください。


3

チームは、理由を出す前に最適化を進めているように思えます。これらのリクエストを実行する時間を測定しましたか?WebサーバーへのラウンドトリップはWebサーバーからデータベースへの接続時間よりもはるかに長いレイテンシーを持つため、このパラダイムがエンドユーザーのパフォーマンスを低下させる可能性があります。その上、ほとんどのWebブラウザーは1つのWebサーバーに対して2つの同時接続のみを行うため、複雑なページではボトルネックに陥る可能性があります。

どちらの方法でも、バックアップするデータがなければ最適化の決定を下すべきではありません。それを測定し、アプリケーションに最適なものを見つけてください。


1
これは私たちの貧弱なパフォーマンス慣行に関する良いコメントですが、DBコールがすでにネットワークコールを持っているときに心配すべきものであるかどうかについての私の質問には答えません。
ashes999 14

1
一般に、複数のデータベース呼び出しを行うことは問題ではないことがわかりました。これは主に、接続プーリングと、DBとWebサーバー間の遅延が小さいためです。多数の異なるdb呼び出しを行うとパフォーマンスに悪影響が出る点がありますが、明確な数値はありません。それはすべて環境とアプリケーションに依存しています。測定するだけで、求める答えが得られます。
ブライアンフェウチ14

私は大きさのオーダーについて話しているので、(必ずしも)詳細に依存するべきではありません。
ashes999 14

大まかな推測(測定する必要があります):WebサーバーからDBに接続する平均時間:2ミリ秒クライアントからWebサーバーに接続する平均時間:20ミリ秒1回のWebサービス呼び出しに要する時間でのデータベース呼び出し。データベースクエリに同じ時間がかかると仮定します。これらの数値は環境に大きく依存しています。Webサービス呼び出しを行うクライアントがローカルの場合、それを数桁落とす可能性があります。
ブライアンフェウチ14

2

わかりません。

クエリがどのようなものかはわかりません。彼らが完了するまでにどれくらいかかるかはわかりません。APIサーバーへの各リクエストにどの程度のオーバーヘッドが含まれるかはわかりません。クライアントがどの程度地理的に分散しているかはわかりません。等。

これが最適化必要とするシナリオであり、呼び出しを分割または結合するかどうかを決定できるシナリオである場合、両方の方法でベンチマークを行う必要があります:最適化対象(UIレイテンシ、サーバーCPU負荷、競合、など)、最適化の目標をよりよく達成できるものを選択します。


それはさておき、唯一の1つの、私は相対的な確信を持って追加することができます事はこれです:

1つの要求内で、応答を作成するために実行する必要があるすべてのクエリを実行する必要があります。

つまり、N個すべてのクエリが実行されるまで応答を生成できない場合、それらを分離するのは通常無意味です。中間または完全にかかわらず、各クエリの後に意味のある結果を生成できる場合は、ベンチマークを開始します。


1

2つの考え:

まず、APIを使用する消費者に対して、彼はタスクを達成するために1つの呼び出しを行っています。サーバーが要求を満たすための呼び出しを受け取った後に何が起こるかはそれほど厳しくはないはずです。コンシューマーからの1つの呼び出しで、データをまとめて返すために10個のサブワークアイテムが必要な場合、それは受け入れられるはずです。

2番目:問題のプロセスに実際のデータベースパフォーマンスの問題がありますか?私の経験では、データベースリクエストのすべての側面を1回の呼び出しにしようとすると、データの呼び出しを3〜4回行うよりも効率の悪い呼び出しになることがよくあります。最新のデータベースは、キャッシングと実行計画において非常に効率的です。多くの場合、やりすぎようとすると、カーソルを使用した手順(一度にセットとしてではなく行ごとにデータが処理されるためパフォーマンスが非常に悪い)と、破損した場合よりも効率の悪い計画になるコードが表示されますいくつかの小さな簡単なステップに呼び出します。

単純なコードの編成から、各API呼び出しが単一のストアドプロシージャ(またはdb関数)を呼び出して、要求を処理する責任を負うことに同意します。手順には複数のステップがある場合があります。


パフォーマンスの測定については同意しますが、誰もそれを行っていないようです。これがより高速であるという証拠はありませんが、これからも増え続けます。たとえば、1000 DBを作成する可能性のある呼び出しがある場合、パフォーマンスが問題として発生しSELECTます。
ashes999 14

@ ashes999は、db呼び出しの数を見ると速度が向上する可能性がありますが、呼び出しの数ではなく、インデックス戦略などで見られる可能性が高くなります。誰もが指摘したように、パフォーマンスデータを見てください。
リチャード14

リチャード、私は同意し、実際にそれを知っています。私の質問は、ネットワークコールが関係しているときに、「複数のDBコールが遅い」という点をさまざまな人々が持ち続けている理由です。私はそれがどのように重要であるかを本当に見ていません。
ashes999 14

@ ashes999申し訳ありませんが、ネットワークコールについてもう少し詳しく説明する必要があるかもしれません。それは明らかなようで、あなたの質問にはもう少しあると思います。私たちはあなたの質問に何かが欠けていると感じています。常にネットワークレイテンシが発生し、各コールは(簡単な言葉で)コールごとに「x」倍増加する可能性があります。額面でのステートメントはtrueです。複数のネットワークコールは、dbへの1つのネットワークコールよりも遅くなります。そのため、マルチプロシージャコールなしでdbを複数回呼び出すことができるストアドプロシージャを1回呼び出すことをお勧めします。
リチャード14

1

データベースがRESTサービスとは異なるサーバー上にある場合、各データベース呼び出しによりネットワークの往復が発生し、パフォーマンス大幅に低下する可能性があります。

一度、1つのWebサービス呼び出しが約500のデータベースクエリに変換されるのを観察しました-これは、Webサービスとデータベースの両方が同じマシンにある場合はほとんど問題ではありませんでしたが、異なる場合は6-7秒の応答時間になりましたマシン。

明らかに、データベースへの500回の往復は非常に極端です。パフォーマンス要件がわからないが、経験則として、REST呼び出しごとに約10のデータベースクエリを下回っていれば、パフォーマンスが大幅に低下することはないはずです。


1

非常におしゃべりなアプリケーションがいくつかあります。毎回データベース呼び出しがあります。シングル。少し。もの。何度も何度も参照データを提供することは、システムのワークロードの主要な部分です。実際のディスクIOがなくても、ワーカースレッドのスケジューリング、ロックの取得とドロップ、プランキャッシュチェックなどがすべて加算されます。トランザクションは複数のDBコール間でロックを保持する必要があるため、競合が高くなります。そのため、スループットは考えられるよりもはるかに低くなります。これらのチームは現在、このために非常に高価な新しいDBサーバーを購入する必要があると考えています。

そのため、システムの現在の構成の経過時間の大部分はREST API呼び出しに費やされますが、DBレベルでのパフォーマンスを無視すると、将来の問題が蓄積されます。


0

提示された最適化パスは、物事を見るための間違った方法です。

API呼び出しはアトミックである必要があります。つまり、1つのWeb API呼び出しを実行して、必要なアクションを実行できる必要があります。データの取得、レコードの更新、その他何でも。アクションを引き起こすために複数の呼び出しを決して取るべきではありません。そして、複数のコールにわたってトランザクションを活用しようとすることは、ペストのように避けるべきです。

単一のアクションがかなり複雑な場合があります。たとえば、複数のソースから結合されたデータを取得する場合、これも単一の呼び出しである必要があります。全体が機能するか、全体が失敗します。

さて、1回のAPI呼び出しで1つのDBクエリのみを実行する必要があると言うのは、少し馬鹿げています。指摘したように、ネットワーク全体でコールをマーシャリングするためのオーバーヘッドは、多くの場合、全体的な時間の観点からはるかに高価です。

単一のクエリの実行は複数のクエリよりも高速であるという声明をある程度理解できます。しかし、これは総DBおよびネットワーク負荷を無視するため、誤った印象を与えます。DBからデータを引き出すさまざまな方法をプロファイリングすることによってのみ、問題が実際に何であるかを知ることができます。特定のクエリが予想よりも100倍頻繁に実行され、適切なインデックスが配置されるまでシステムが強制終了されるという話は誰もが知っているはずです...

最終的に、あなたは彼らにただ話すだけで納得させることはできません。両方のアプローチのテストケースを設定し、プロファイルします。必要なデータを取得するための合計時間、生成されるネットワークトラフィックの量、データベースコールの数やタイミングなどに注意してください。全体的なアプローチを取ります。つまり、システム全体を見ることになります。カラスを食べるか、ゴールデンパスを表示するデータ。

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