1. ホーム
  2. database-design

[解決済み] MongoDBスキーマ設計 - 小さなドキュメントを多くするか、大きなドキュメントを少なくするか?

2023-01-13 06:15:03

質問

背景

私は、RDBMSデータベースからMongoDBへの変換のプロトタイプを作成しています。非正規化の間、私には2つの選択肢があるように思えます。1つは多くの(数百万)より小さいドキュメントにつながり、もう1つは少ない(数十万)より大きいドキュメントにつながるものです。

単純なアナログに落とし込むとすれば、このような(Javaの)Customerドキュメントが少ないコレクションかどうかの違いです。

クラス Customer {
    private String name;
    private Address address;
    // 各CreditCardは数百のPaymentインスタンスを持っています。
    private Set<CreditCard> creditCards;


または、このような多数のPaymentドキュメントを持つコレクションです。

クラス Payment {
    private Customer customer;
    private CreditCard creditCard;
    private Date payDate;
    private float payAmount;


質問

MongoDBは多数の小さなドキュメントと少数の大きなドキュメントのどちらを好むように設計されていますか?答えは、私が実行する予定のクエリにほとんど依存しますか?(例: 顧客 X は何枚のクレジットカードを持っているか? vs 先月のすべての顧客の平均支払額はいくらだったか?)

私はたくさん見て回りましたが、私の質問に答えるのに役立つような MongoDB スキーマのベストプラクティスに出くわしたことはありません。

どのように解決するのですか?

やっているクエリに最適化する必要があるのは間違いないでしょう。

あなたの説明に基づいて、私の最善の推測は以下のとおりです。

おそらく、各顧客のすべてのクレジットカードを知りたいと思うので、顧客オブジェクト内にそれらの配列を保持します。また、おそらく各支払いに顧客参照を持ちたいと思うでしょう。これは、Paymentドキュメントを比較的小さく保つことができます。

Paymentオブジェクトは、自動的に独自のIDとインデックスを持つことになります。おそらく、顧客参照にもインデックスを追加したいと思うでしょう。

これにより、毎回顧客オブジェクト全体を保存することなく、顧客によるPaymentを素早く検索することができます。

次のような質問に答えたい場合 先月、すべての顧客が支払った平均額はいくらですか。 のような質問に答えたいのであれば、どんな大きなデータセットでも map / reduce が必要でしょう。この応答は、リアルタイムでは得られません。Customerへのquot;reference;を保存することは、おそらくこれらのマップリダクションのために十分であることがわかります。

では、ご質問に直接お答えします。 MongoDBは多数の小さなドキュメントと少数の大きなドキュメントのどちらを好むように設計されていますか?

MongoDBはインデックスされたエントリーを非常に速く見つけるように設計されています。MongoDBはインデックス付きのエントリーを見つけるのがとても得意です。 少数 を見つけるのが得意です。MongoDBは ではなく を見つけるのはあまり得意ではありません。 最も を見つけるのが得意です。ですから、最も一般的なユースケースを中心にデータを構築し、稀なユースケースのためにマップ/リデュースジョブを書きましょう。