21

数十億の小さなデータ構造 (それぞれ約 200 バイト) を格納する必要があります。これまでのところ、各要素を個別のドキュメントとして保存することはうまく機能しており、Mongo は 1 秒あたり約 10,000 件の結果を提供しています。各ドキュメントの _id として 20 バイトのハッシュを使用し、_id フィールドに単一のインデックスを使用しています。テストでは、これは 5,000,000 ドキュメントのデータ セットで機能しています。

運用中は、1 秒あたり約 10,000 のリクエストを行い、既存のドキュメントを 1 秒あたり約 1,000 回更新し、新しいドキュメントを 1 秒あたり 100 回またはそれ以下で挿入します。

インデックス全体を RAM に保存できない場合、より大きなデータ セットをどのように管理できますか? 複数の要素を各ドキュメントに結合すると、MongoDB のパフォーマンスは向上しますか?インデックスを介した検索を高速化しますが、各クエリで返されるデータは増えますか?

SO に関する他の質問とは異なり、Mongo にどれだけのデータを詰め込めるかだけに関心があるわけではありません。私たちが見ているデータの量を明確に管理できます。find私の懸念は、RAM に制約がある場合に、巨大なコレクションの操作速度を最大化するにはどうすればよいかということです。

検索はクラスター化される傾向があります。約 50,000 の要素がクエリの約 50% を満たしますが、残りの 50% はすべてのデータにランダムに分散されます。最も頻繁に使用されるデータの小さいインデックスを常に RAM に保持するために、これらの 50% を独自のコレクションに移動することで、パフォーマンスの向上を期待できますか?

_id フィールドのサイズを 20 バイトから 8 バイトに減らすと、MnogoDB のインデックス作成速度に大きな影響がありますか?

4

1 に答える 1

28

いくつかの戦略が思い浮かびます。

1) 「ホット」なドキュメントには個別のコレクション/データベースを使用します。

どのドキュメントがホット セットにあるかがわかっている場合は、はい、それらを別のコレクションに移動すると役立ちます。これにより、ホット ドキュメントが同じエクステント/ページに共存することが保証されます。また、これらのドキュメントのインデックスが完全にメモリ内にある可能性が高くなります。これは、サイズが小さくなり、(完全に?) 頻繁に使用されるためです。

ホット ドキュメントが他のドキュメントとランダムに混在している場合は、別のドキュメントが最近インデックス ブロックをロードまたはアクセスした可能性が低いため、ドキュメントをロードするときに、B ツリー インデックスのより多くのリーフ要素でエラーが発生する可能性があります。

2) インデックス値を短くします。

インデックス値が短いほど、1 つの B-Tree ブロックに収まる値が多くなります。(注: キーはインデックスに含まれません。) 1 つのバケット内のエントリが多いほど、インデックスに必要なバケットと総メモリ量が少なくなります。これは、ブロックがメモリにとどまる可能性が高くなり、寿命が長くなることを意味します。あなたの例では、20->8 文字の削減は、50% の節約よりも優れています。これらの 8 バイトを long に変換できる場合、long には長さのプレフィックス (4 バイト) と末尾の null (合計 5 バイト) がないため、もう少し節約できます。

3) キー名を短くします。

フィールド名が短いほど、各ドキュメントが占めるスペースが少なくなります。これには、可読性が低下するという不幸な副作用があります。

4) シャード

これは、メモリと最終的なディスク帯域幅を使い果たすコーパス全体にわたる読み取りに直面して、パフォーマンスを維持する唯一の方法です。シャードを行う場合でも、「ホット」コレクションをシャードする必要があります。

5)ディスクの先読みを小さな値に調整します。

「非ホット」読み取りはディスクからランダムなドキュメントをロードしているため、実際にはそのドキュメントとその周りのドキュメントをできるだけ少なくしてメモリに読み込み/障害を起こしたいと考えています。ほとんどのシステムは、ユーザーがファイルの一部から読み取ると、大きなデータ ブロックを先読みしようとします。これは、私たちが望んでいることとは正反対です。

システムで多くの障害が発生しているのに、mongod プロセスの常駐メモリがシステムで使用可能なメモリに近づいていない場合は、OS が無駄なデータを読み取っている影響が見られる可能性があります。

6) キーに対して単調に増加する値を使用してみてください。

これにより、最適化 (ObjectId ベースのインデックスの場合) がトリガーされ、インデックス ブロックが分割されるときに 50/50 ではなく 90/10 で分割されます。その結果、インデックス内のほとんどのブロックがほぼ容量に達し、必要なブロックが少なくなります。

事後に「ホットな」50,000 ドキュメントしか知らない場合は、それらを別のコレクションにインデックス順に追加すると、この最適化もトリガーされます。

ロブ。

于 2013-07-22T01:05:32.310 に答える