5

私はC++/ Qtでプロジェクトを作成しており、QtSQL(http://doc.qt.nokia.com/latest/qtsql.html )でサポートされている任意のタイプのSQLデータベースに接続できます。これには、ローカルサーバーと外部サーバーが含まれます。

ただし、問題のデータベースが外部にある場合、クエリの速度が問題になり始めます(UIが遅いなど)。理由:データベースに格納されているすべてのオブジェクトは遅延読み込みされるため、属性が必要になるたびにクエリが発行されます。これらのオブジェクトのうち平均して約20個が画面に表示され、それぞれに約5個の属性が表示されます。これは、表示するすべての画面で約100個のクエリが実行されることを意味します。クエリはデータベースサーバー自体で非常に高速に実行されますが、ネットワーク上で実行される実際のクエリのオーバーヘッドはかなりのものです(画面全体で数秒で測定)。

私はこの問題を解決するためのいくつかの方法を考えてきましたが、最も重要なアプローチは(私によれば)次のようです:

  1. クエリを減らす
  2. クエリを高速化

タックル(1)

  • 属性の実際のフェッチを遅らせる(トランザクションを開始する)方法を見つけることができ、プログラマーがendTransaction()を書き込むと、データベースはすべてを一度にフェッチしようとします(SQL UNIONまたはループを使用...) 。これはおそらく怠惰なオブジェクトの動作方法にかなりの変更を加える必要がありますが、人々がそれがまともな解決策であるとコメントした場合、私はそれがエレガントに解決できると思います。このソリューションがすべてを十分に高速化する場合、複雑なキャッシュスキームは必要ないかもしれず、多くの頭痛の種を節約します
  • 要求されたすべてのオブジェクトに対して1つのクエリですべてをフェッチすることで属性データをプリロードして、効果的に遅延をなくすことができます。もちろん、その場合、私は古いデータについて心配する必要があります。少なくとも1つのクエリを外部データベースに送信せずに古いデータを検出するにはどうすればよいですか?(注:すべての属性チェックで失効したデータをチェックするクエリを送信すると、データが実際に失効していることが判明した場合に、最良の場合は0倍のパフォーマンスが向上し、最悪の場合は2倍のパフォーマンスが低下します

タックル(2)

たとえば、データベースのローカル同期コピーを実行し続けることで、クエリを高速化できます。ただし、クライアントマシンで、たとえばサーバー上のデータベースタイプとまったく同じデータベースタイプを実行する可能性はあまりありません。したがって、ローカルコピーはたとえばSQLiteデータベースになります。これは、db-vendor固有のソリューションを使用できなかったことも意味します。ここでの私のオプションは何ですか?このような状況で人々にとって何がうまくいったのでしょうか?

心配事

私の主な心配事は次のとおりです。

  • 古いデータ:古いデータを持つユーザーには可能と思われるアクションを禁止するような方法でデータベースを変更する、考えられるクエリはたくさんあります。
  • 保守性:この新しいレイヤーでどの程度緩く結合できますか?私の内部の怠惰なオブジェクトシステムとすべてのオブジェクトと可能なクエリについてすべてを知る必要がなければ、明らかに望ましいでしょう。

最後の質問

クエリを作成するコストを最小限に抑えるための良い方法は何でしょうか?良い意味は、次のような組み合わせのようなものです。保守可能で、実装が簡単で、アプリケーション固有ではありません。いずれか2つを選ぶことになった場合は、そうしてください。人々が彼らの経験とそれを解決するために何をしたかについて話してもらいたいです。

ご覧のとおり、私はいくつかの問題とそれを処理する方法を考えましたが、賢明なアプローチを構成するものについては途方に暮れています。プログラムの多くのレイヤーにかなりの作業と集中的な変更が必要になる可能性があるため(できればできるだけ少ない)、この問題について最終決定を下す前に、ここですべての専門家に質問することを考えました。非常に単純な解決策を見落としている可能性もあります。その場合は、それへのポインタをいただければ幸いです。

関連するすべてのサーバー側の調整が行われたと仮定します(例:MySQLキャッシュ、可能な限り最高のインデックス、...)

*注:同様の問題を抱えているユーザーの質問を確認しましたが、私の質問を完全には満たすことができませんでした:私のユースケースのレプリケーションスキームに関する提案?ローカルデータベースキャッシュのベストプラクティスは?例えば)

回答を提供するために追加情報が必要な場合は、お知らせください。質問を適切に更新します。スペル/文法の誤りについてお詫びします。英語は私の母国語ではありません。

「怠惰」についての注意

私のコードがどのように見えるかの小さな例(もちろん簡略化されています):

QList<MyObject> myObjects = database->getObjects(20, 40); // fetch and construct object 20 to 40 from the db

// ...some time later

// screen filling time!
foreach (const MyObject& o, myObjects) {
    o->getInt("status", 0);  // == db request
    o->getString("comment", "no comment!"); // == db request
    // about 3 more of these
}
4

1 に答える 1

2

一見すると、競合する 2 つの目標があるように見えます。クエリの速度と、常に最新のデータを使用することです。したがって、ここで決定するのを助けるために、おそらくあなたのニーズに頼るべきです.

1) アプリケーションの使用に比べて、データベースはほとんど静的です。この場合、オプションを使用して1bすべてのデータをプリロードします。下のデータが変更される可能性がほとんどない場合は、ユーザーにキャッシュを更新するオプションを提供します (完全に、またはデータの特定のサブセットに対して)。このようにして、低速アクセスはユーザーの手に委ねられます。

2) データベースはかなり頻繁に変更されます。この場合、「おそらく」SQL データベースはニーズに適していません。プルを要求するのではなく、更新をプッシュする高性能の動的データベースが必要になる場合があります。そうすれば、基になるデータが変更されたときにアプリケーションに通知され、迅速に対応できます。それでもうまくいかない場合は、クエリを作成して、DB ライブラリと I/O 呼び出しの数を最小限に抑える必要があります。たとえば、一連のselectステートメントを実行すると、結果には、要求した順序ですべての適切なデータが含まれている必要があります。対応する選択ステートメントが何であったかを追跡するだけです。または、より緩いクエリ基準を使用して、単純なクエリに対して複数の行を返すことができれば、パフォーマンスも向上します。

于 2011-08-01T14:19:48.733 に答える