web-dev-qa-db-ja.com

MongoDB:ドキュメントのサイズはクエリのパフォーマンスに影響しますか?

数百万のドキュメントを含むUserコレクションを含むMongoDBデータベースに支えられたモバイルゲームを想定します。

次に、ユーザーに関連付ける必要がある数十のプロパティを想定します。 Friendドキュメントの_id値の配列、ユーザー名、写真、Gameドキュメントの_id値の配列、last_loginの日付、ゲーム内通貨の数、などなど。

私の懸念は、何百万ものユーザードキュメントで大規模に成長するアレイを作成および更新すると、各ユーザードキュメントに「重み」が追加されるか、システム全体の速度が低下するかどうかです。

ドキュメントごとに16MBのEclipseを実行することはおそらくないでしょうが、これらの増大するリストを直接保存すると、ドキュメントが10〜20倍大きくなると言うことができます。

質問:これはMongoDBの問題でもありますか?クエリがプロジェクションやインデックスなどを使用して適切に管理されている場合でも、ドキュメントのサイズは重要ですか?たとえば、外部リストと埋め込みリストの参照など、ドキュメントサイズを積極的に削減する必要があります。 _id値の直接?

言い換えると、ユーザーのlast_login値が必要な場合、Userドキュメントが100kbと5mbの場合、last_loginフィールドのみを投影/選択するクエリは異なりますか?

または:特定のlast_login値を持つすべてのユーザーを検索する場合、ドキュメントサイズはその種類のクエリに影響しますか?

26
toblerpwn

まず最初に、パディングファクターとpowerof2sizesの割り当てに関連して、MongoDBがドキュメントをどのように格納するかについて少し時間をかけて読む必要があります。

http://docs.mongodb.org/manual/core/storage/http://docs.mongodb.org/manual/reference/command/collStats/#collStats.paddingFactor

簡単に言うと、MongoDBは、元のドキュメントを格納するときに追加のスペースを割り当てて、拡張できるようにします。 Powerof2sizes割り当ては、バージョン2.6でデフォルトのアプローチになり、ドキュメントサイズが2の累乗で増加します。

全体として、すべての更新が元のサイズ割り当て内に収まる場合は、パフォーマンスが大幅に向上します。その理由は、そうでない場合、ドキュメント全体を十分なスペースのある別の場所に移動する必要があるため、読み取りと書き込みが多くなり、実際にはストレージが断片化するためです。

ドキュメントのサイズが実際に10倍から20倍の時間で増加すると、ドキュメントごとに複数の移動が発生する可能性があり、挿入、更新、読み取りの頻度によっては問題が発生する可能性があります。その場合は、いくつかのアプローチを検討できます。

1)最初の挿入時に十分なスペースを割り当てて、通常のドキュメントの存続期間の増加のほとんど(90%としましょう)をカバーします。これは最初はスペースの使用において非効率ですが、パフォーマンスを低下させることなくドキュメントが大きくなるにつれて、効率は時間とともに増加します。実質的には、将来的に優れたパフォーマンスを得るために後で最終的に使用するストレージに前払いします。

2)「オーバーフロー」ドキュメントを作成します-典型的な80-20ルールが適用され、ドキュメントの80%が特定のサイズに収まるとしましょう。その量に割り当てて、たとえば100人を超える友達や100個のゲームドキュメントがある場合に、ドキュメントが指すオーバーフローコレクションを追加します。オーバーフローフィールドはこの新しいコレクション内のドキュメントを指し、アプリはオーバーフローフィールドが存在する場合にのみ新しいコレクションを調べます。ユーザーの80%で通常のドキュメント処理が可能になり、アプリケーションの複雑さが増すことで、不要な80%のユーザードキュメントで大量のストレージを無駄にすることがなくなります。

どちらの場合も、適切なインデックスを作成して、対象クエリを使用することを検討します。

対象クエリは、次のようなクエリです。

all the fields in the query are part of an index, and
all the fields returned in the results are in the same index.

インデックスはクエリを「カバー」するため、MongoDBはクエリ条件に一致し、インデックスのみを使用して結果を返すことができます。 MongoDBは、クエリを実行するために、ドキュメントのみを参照する必要はなく、インデックスのみを参照します。

インデックスのみのクエリは、インデックス外のドキュメントのクエリよりもはるかに高速です。インデックスキーは通常、それらがカタログ化するドキュメントよりも小さく、インデックスは通常、RAMで利用できるか、ディスク上に順番に配置されます。

ここでそのアプローチの詳細: http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/

14
John Petrone

質問を言い換える1つの方法は、ドキュメントがそれぞれ16MB対16KBである場合、100万のドキュメントクエリはより長くかかるということです。

私が間違っている場合は修正してください。自分の経験から、ドキュメントサイズが小さいほど、クエリは高速になります。

500kドキュメントに対してクエリを25kドキュメントに対して実行しましたが、25kクエリは著しく高速で、数ミリ秒から1〜3秒の範囲で高速でした。製造時の時間差は約2x-10xです。

ドキュメントサイズが関係する1つの側面はクエリの並べ替えです。この場合、ドキュメントサイズはクエリ自体が実行されるかどうかに影響します。 2,000回ものドキュメントを並べ替えようとすると、何度もこの制限に達しました。

ここにいくつかの解決策の参照があります: https://docs.mongodb.org/manual/reference/limits/#operationshttps://docs.mongodb.org/manual/reference/ operator/aggregation/sort /#sort-memory-limit

結局のところ、苦しんでいるのはエンドユーザーです。

大きなクエリを修正しようとすると、パフォーマンスが許容できないほど遅くなります。私は通常、データのサブセットを使用して新しいコレクションを作成し、並べ替えと制限と共に多くのクエリ条件を使用しています。

お役に立てれば!

10
Richard Kuo