2016-10-20 8 views
2

私はMongodbを初めて使っています.Mongodbは大量の読み書き操作に適していると聞きました。 埋め込みドキュメントは、それを実現する機能の1つです。しかし、パフォーマンスの問題の原因であるかどうかはわかりません。 ブック文書の例:Mongodbの埋め込みドキュメントを更新してください:パフォーマンスの問題?

{ 
    "_id": 1, 
    "Authors": [ 
     { 
      "Email": "email", 
      "Name": "name" 
     } 
    ], 
    "Title": "title", 
    ... 
} 

が1本の著者の書籍の数千人がおり、彼の電子メールを更新する必要がある場合は、私はすべての書籍の文書を

  1. 検索をすることができますいくつかのクエリを記述する必要があり、これらの操作は、EFFはいないようですこれらの帳簿書類

渡ってこの作者

  • 更新著者のメールフィールドを持つもの何千ものものを選びますicient。しかし、このタイプのアップデートはどこにでもあります。私は開発者がこれを考慮したと信じています。それで、どこが間違っていたのですか?

  • 答えて

    1

    現在の埋め込みスキーマ設計にはメリットがありますが、そのうちの1つはデータローカリティです。 MongoDBはディスク上にデータを連続して格納するので、必要なすべてのデータを1つのドキュメントに格納することで、回転ディスクのディスクへの特定の場所へのシーク時間が短縮されます。

    アプリケーションがbooksの情報とAuthorsのデータに頻繁にアクセスする場合、ほとんどの場合、埋め込みルートに行きたいと思うでしょう。埋め込まれたドキュメントのもう1つの利点は、データを書き込む際のアトミック性と分離です。これを説明するために

    は、あなたが1人の著者によってすべての書籍は、彼の電子メールのフィールドが更新されていたいと、これはMongoDBの持つパフォーマンスの問題ではありません1つの(原子)の操作で行うことができます。

    db.books.updateMany(
        { "Authors.name": "foo" }, 
        { 
         "$set": { "Authors.$.email": "[email protected]" } 
        } 
    ); 
    

    上記で

    db.books.update(
        { "Authors.name": "foo" }, 
        { 
         "$set": { "Authors.$.email": "[email protected]" } 
        }, 
        { "multi": true } 
    ) 
    

    、明示的にELの位置を指定せずに更新する配列の要素を識別することによって、埋め込み文書を含むアレイへの更新を容易にpositional $ operatorを使用する:以前のMongoDBバージョンと配列内の要素。 $オペレータのdot notationと一緒に使用してください。

    MongoDBのデータモデリングの詳細については、文書Data Modeling Introduction、特にModel One-to-Many Relationships with Embedded Documentsをお読みください。


    他の設計オプションは、正規化されたスキーマに従うドキュメントを参照することです。たとえば:あなたは非常に予測不可能なアリティと1対多の関係を持っているとき

    // db.books schema 
    { 
        "_id": 3 
        "authors": [1, 2, 3] // <-- array of references to the author collection 
        "title": "foo" 
    } 
    
    // db.authors schema 
    /* 
    1 
    */ 
    { 
        "_id": 1,  
        "name": "foo", 
        "surname": "bar", 
        "address": "xxx", 
        "email": "[email protected]" 
    } 
    /* 
    2 
    */ 
    { 
        "_id": 2,  
        "name": "abc", 
        "surname": "def", 
        "address": "xyz", 
        "email": "[email protected]" 
    } 
    /* 
    3 
    */ 
    { 
        "_id": 3,  
        "name": "alice", 
        "surname": "bob", 
        "address": "xyz", 
        "email": "[email protected]" 
    } 
    

    文書参照アプローチを用いて、上記の正規化されたスキーマにも利点があります。帳簿エンティティごとに数百または数千の著者文書がある場合、文書のサイズが大きくなればなるほど、MongoDB文書のハードサイズは16MBに制限されるため、埋め込みには空間的制約が関係する限り、多くの難点があります。

    正規化されたスキーマを照会するためには、左の外側は、処理のためにbooksコレクションからの文書にフィルタリングする同じデータベースにauthorsコレクションに参加行うアグリゲーションフレームワークの$lookup演算子の使用を検討することができます。


    は、このように私はあなたの現在のスキーマが別々のコレクションが本を見つけること、すなわち、より多くの作業が必要+その著者らは2つのクエリで、上記のスキーマのに対し、余分な作業を必要とするためauthorsの分別収集を作成するよりもより良い方法であると考えて、言いました埋め込みドキュメントは簡単で高速です(シングルシーク)。挿入と更新に大きな違いはありません。したがって、個々のドキュメントを選択したり、クエリを制御したり、巨大なドキュメントを必要とする場合は、別々のコレクションが適しています。埋め込みドキュメントは、ドキュメント全体が必要な場合は$slice、埋め込みドキュメントがauthors、またはauthorsでない場合にも便利です。

    一般的な経験則では、アプリケーションのクエリパターンがよく知られており、データが一方向にしかアクセスされない場合、埋め込みアプローチがうまく機能するということです。アプリケーションがさまざまな方法でデータを照会したり、データクエリパターンを予測できない場合は、より正規化されたドキュメント参照モデルがそのような場合に適しています。

    参考:

    MongoDB Applied Design Patterns: Practical Use Cases with the Leading NoSQL Database By Rick Copeland

    0

    私はあなたが基本的に間違ったスキーマ設計を持っていると思います。 MongoDBでは、データを階層的に構造化することができますが、非効率的に構造化することはできません。コレクション全体で何千ものドキュメントを定期的に更新する必要がある場合は、適切なスキーマ設計があるかどうかを確認する必要があります。

    スキーマ設計とリレーショナルDB構造との比較については、多くの記事があります。例: http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1

    関連する問題