メモリからのデータの挿入とクエリのベスト プラクティス
-
02-10-2019 - |
質問
リアルタイムのデータを取得してデータベースに挿入するアプリケーションがあります。1日あたり4.5時間オンラインです。17 個のテーブルにデータを秒ごとに挿入します。ユーザーはいつでも、任意のテーブルに対して最新の 2 番目のデータや履歴のレコードをクエリできます。
フィードと挿入の処理は、C# コンソール アプリケーションを使用して行われます。
ユーザー要求の処理は、WCF サービスを通じて行われます。
私たちは、挿入がボトルネックであることを発見しました。ほとんどの時間はそこに取られます。テーブルとインデックスを微調整するために多くの時間を費やしましたが、結果は満足のいくものではありませんでした
十分なメモリがあると仮定して、データベースの代わりにメモリにデータを挿入するベスト プラクティスは何ですか。現在、私たちの同僚は、フィードハンドラーとWCFユーザーレクエストハンドラーの間のデータベースの代わりに別のWCFサービスを提案した毎秒更新および挿入されたデータテーブルを使用しています。WCF 中間層は TCP ベースであると想定されており、データを独自のメモリに保持します。フィード ハンドラーは 2 つのプロセスの間に中間層を設ける代わりにユーザーのリクエストを処理するかもしれないと言われるかもしれませんが、フィード ハンドラーがクラッシュした場合でもユーザーに現在のレコードを提供できるように、物事を分離したいと考えています。
時間は限られているので、短時間ですべてを記憶に移したいと考えています。2 つのプロセスの途中に WCF を置くのは悪いことですか?リクエストによってオーバーヘッドが追加されることはわかっていますが、これら 3 つのプロセス (フィード ハンドラー、インメモリ データベース (WCF)、ユーザー リクエスト ハンドラー (WCF)) はすべて同じマシン上にあり、帯域幅はそれほど大きくありません。問題の。
手伝ってください!
解決
データのキャッシュを作成し(データベースの選択も減らすことができるように)、データベースに書き込まれた後にキャッシュ内のデータを無効にすることを検討します。こうすることで、呼び出しをバッチ化して、多数の小さな挿入ではなく、より大きな挿入を行うことができますが、リーダーが読み取れるようにデータをメモリ内に保持することができます。実際、データがいつ失効するかがわかっていれば、データベース全体の読み取りを回避し、データベースをバッキング ストアとしてのみ使用できます。この方法では、データベースのパフォーマンスはキャッシュのサイズにのみ影響します。
キャッシュ内のデータの無効化は、そのデータがデータベースに書き込まれたか、古くなったかに基づいて行われます。 最後, 、最初ではありません。
キャッシュ レイヤーは複雑である必要はありませんが、データをホストし、バックグラウンドで保存するためにマルチスレッドである必要があります。この層は、接続メディアである WCF サービスのすぐ後ろに位置し、コンソール アプリのロジックとバッチ処理のアイデアを含めるように WCF サービスを改善する必要があります。その後、コンソール アプリは WCF に接続して結果をスローするだけです。
アップデート: 他に言えることは、プロファイラーに投資して、マスクされているコードにパフォーマンスの問題が発生していないかどうかを確認することです。また、データベースのプロファイリングも行います。高速な挿入と選択が必要だとおっしゃいましたが、残念ながら、これらは通常、相互にトレードオフになります...
他のヒント
どのようなデータベースを使用していますか?MySQL には、この種のことに適していると思われるストレージ エンジン MEMORY があります。
DataAdapter で DataTable を使用していますか?もしそうなら、完全に削除することをお勧めします。DBCommand を使用してレコードを直接挿入します。ユーザーがレポートを要求する場合は、DataReader を使用してデータを読み取るか、DataTable.Load (IDataReader) を使用して DataTable オブジェクトを設定します。
メモリ内のストーリー データには、クラッシュや停電が発生した場合にデータが失われるリスクがあります。