10

私は、MongoDB データベースから MySQL データベースにデータを移植する任務を負っています。(移植には強い理由があるため、移植する必要あります)。

MongoDB コレクション:

  • 約 1 億 1000 万のドキュメントがあります
  • サイズは 60 GB です
  • 重要なプロパティのインデックスがあります
  • 本番トラフィックを処理していない Windows 2008 スタンドアロンの別のサーバーを実行している

試したセットアップ:

  • 7.5 ギガの RAM / 8 ギガのページ ファイルを備えた大規模な Amazon EC2 Win2008 サーバー インスタンス
  • MongoDB データをローカルの MySQL データベースに変換する AC# コンソール アプリ

MongoDB からメモリ内で一度に 1,000 個のドキュメントを取得し、必要な処理を行ってから、一度に 500 個のバッチ書き込みを行って MySQL データベースに保存します。

私たちが直面している問題は、250 万のドキュメントごとにサーバーが停止し、Mongo の応答が非常に遅くなることです。つまり、アプリのデータ取得操作がタイムアウトします (100 万のドキュメントが処理されるまでに空き RAM が処理されます)。

mongod プロセスを強制終了し、クラッシュしたときに 250 万レコードごとに再起動することで、ゆっくりと前進していますが、何か間違ったことをしているに違いありません。

質問:

このために、Mongo Server を Linux ベースの L インスタンスに移動し、MySQL を Amazon RDS に移動して、PHP で変換アプリを書き直す必要がありますか? それは役に立ちますか?

すべてを 1 つのボックスに保持することにした理由は、異なるサーバーに異なるサーバーを配置することによる遅延の問題でした。

他に試してみることができること/使用できるヒントは何ですか?

ここまで読んでくれてありがとう!

-- アップデート 01 --

アプリを再起動してから約 6 時間経過し、次の変更を加えました。

  1. Mongo Read カウントが一度に 1,000 から 10,000 レコードに増加しました。.skip(10K).limit(10K)
  2. MySQL ターゲット データベースからすべてのインデックスを削除しました。
  3. Windows ページ サイズを 4 ギガから 8 ギガに増加

メモリは 100% 消費されていますが、アプリはまだ実行されています。(前回は52分で鳴きました)。Mongo は 6.8 ギガの RAM、MySQL - 450 メガバイト、およびコンバーター アプリ - 400 メガ (概算値) を消費します。

これまでに 11M レコードを処理しましたが、速度は約 500 レコード/秒から 370 レコード/秒に低下しました。

次のステップは、Mongo サーバーと MySQL サーバーの両方を別々のボックスに分離し、それらすべてを同じ Amazon アベイラビリティ ゾーンに保持してレイテンシを最小限に抑えることです。

-- アップデート 02 --

Mongo Cursor を使用するようにコードを変更し、.skip().limt() を自分で実行するのとは対照的に、自動的に自動インクリメントできるようにしました。これによりプロセスが大幅に高速化され、以前の 300 レコードから 1 秒あたり 1250 レコードを処理していました。しかし、アプリケーションが大量のメモリを消費し始め、RAM が不足してクラッシュし、2M レコードごとに再起動する必要がありました。

次のコード スニペットを使用しました。

var docs = db[collectionName].Find(query);
docs.SetBatchSize(numOfResultsToFetchAtATime);
foreach (var d in docs) {
  // do processing
}

したがって、これは一度に 'numOfResultsToFetchAtATime' レコードをフェッチしますが、ループ内で自動的に進行し、次のレコード セットをフェッチします。Mongo は Cursor を使用してこの進行を処理するため、はるかに高速です。

ただし、これはまだ移植に成功していません。それが適切に行われると、私の返信をコードで投稿します。

-- アップデート 03: 成功 --

最終的に、mongoexport を実行するという @scarpacci の提案を使用しました。mongodb が Windows ボックスではなく Linux ボックスにあることが不可欠であることを覚えておいてください。

最初に、ローカルの MongoDB で Windows から mongoexport を実行しようとしましたが、何を試しても、1 つの大きなコレクション (13Gigs+) のさまざまな場所で失敗しました。

最後に、Linux ボックスで DB を復元したところ、mongoexport は魅力的に機能しました。

Json -> MySQL コンバーターはありません。少し調整するだけで、以前のアプリを使用してファイルを読み取り、MySQL に直接書き込むことができました。それは迅速で、比較的エラーはありませんでした。

大きなファイルにはいくつか問題がありましたが、13 GB のファイルを 500 MB の長いファイルに分割することで問題が解決し、すべてのデータを MySQL に正常に移行することができました。

時間を割いて私たちを助けてくれた皆さんに感謝します。この説明が将来誰かに役立つことを願っています。

4

5 に答える 5

3

.NET を使用して SQLServer にデータを移行する際に問題が発生したことがあります。最終的に、簡単な C++ OLEDB アプリを作成したところ、作業が大幅に高速化されました。.NET アプリで何が間違っていたのかをまだ解明しようとしていますが、.NET に問題がある可能性があります。私は PHP で変換を書き直すつもりはありませんが、パフォーマンス オプションを使用して C++ を使用します (Web からチュートリアルを入手してください。それほど難しくなく、使い捨てのアプリではありません)。

そのため、最初に確認する必要があるのは、C# アプリのプロファイルを作成して、システムの残りの部分をゆっくりとクロールさせるメモリ リークのバグがないかどうかを確認することです。

他のものではなく、MongoDB アプリを停止するのは面白いと思います。他のシステムではなく、MongoDB が死にかけていると考える理由は何ですか? そのメモリ使用量の場合、個別のボックスに分割すると違いが生じる可能性があります。メモリがゆっくりと増加する場合は、チャンクの読み取りが少なくなります-Mongoはデータの読み取りに問題がないはずです。構成またはアプリでメモリを保持します。

perfmon を起動して、Mongo、アプリ、MySQL インスタンスのメモリ、スワップ、ディスク IO、CPU の使用状況を確認します。

于 2012-07-21T15:21:16.353 に答える
3

大きなデータベース (60 GB ではありませんが、問題を表示するのに十分な大きさ) を移行すると、仕事をする小さなアプリを作成することになりました。

そのようにして、ある種のバッチモードで、あるDBから読み取り、別のDBに書き込みました(データベースのクラッシュなどで同様の問題に直面していました)

私が行ったことは、パーツごとに小さなトランザクションを生成し、作業項目が解決されるたびにそれらを閉じることでした。

両方のデータベースにテーブルがあり、ドキュメントはありませんでしたが、問題は同じです。

結局:

  • 移行を調整するアプリケーションが 1 つありますが、独自のデータベース接続はありません。
  • 調整アプリから生成された複数のインスタンスは、データを移動し、作業項目を実行し、その後閉じます (閉じる前に成功を報告する何らかの方法があります) そうすれば、複数のリーダー/ライターを持つことができ、カウントを試すことができます。約 10 個しかありませんでした。一度に同時読み取り/書き込みインスタンス。ドキュメントが十分に小さい場合は、さらに多くのドキュメントを生成できます。しかし、とにかく非常に速く閉じます。

注:ターゲット データベースにインデックスを作成しないでください。書き込みを行うとパフォーマンスが大幅に向上します。すべてのデータが揃ったら、インデックスを設定します。

于 2012-07-21T16:25:31.293 に答える
3

データを直接 MySQL に書き込む理由はありません - ジョブを 2 つの別々の段階に分割し、最初に MongoDB を実行し、次に MySQL を実行して、リソースを競合しないようにします - 成長する MySQL プロセスが Mongo を飢えさせているようですRAMまたはio上。

ステージ 1: MongoDB からデータを取得して処理し、テキスト ファイルに (SQL として) 保存します。Mongo を停止し、MySQL を開始します

ステージ 2: ステージ 1 で生成されたファイルを使用して、通常のデータベース インポートを実行します。

于 2012-07-21T17:39:28.510 に答える
2

MongoDB を再起動するとパフォーマンスの問題が修正され、問題が発生する前に処理できる一貫した数のレコードが修正されるという事実は、私にはリソース リークのように思えます。すべてが閉じられていることなどを確認します.MySQLがメモリを使いすぎるように構成されていないことを確認するか、別のマシンに移動してください。

于 2012-07-21T17:32:17.543 に答える
1

mongoexportを使用してから、MySQlに何らかの一括挿入を実行することを検討しましたか? それが MySql で利用できるかどうかはわかりませんが、SQL Server では常に同様のことを実行しています。ダンプ/挿入を分割して最適化するのが簡単になる可能性がありますか? ちょっとした考え....

于 2012-07-21T16:12:21.367 に答える