1

私はまだスキーマのないドキュメント指向データベースの使用に慣れてきており、アプリケーション モデル内のスキーマ設計に関して一般的に受け入れられている慣行について疑問に思っています。

具体的には、次のようにmongodbに保存するときに、アプリケーションモデル内でスキーマを適用することをお勧めするかどうか疑問に思っています:

{
    _id: "foobar",
    name: "John"
    billing: {
        address: "8237 Landeau Lane",
        city: "Eden Prairie",
        state: "MN",
        postal: null
    }
    balance: null,
    last_activity: null
}

次のように使用されるフィールドのみを保存するのに対して:

{
    _id: "foobar",
    name: "John"
    billing: {
        address: "8237 Landeau Lane",
        city: "Eden Prairie",
        state: "MN"
    }
}

前者は自己記述的で私が気に入っていますが、後者はモデル スキーマの可変性について何も仮定していません。

最初のオプションは、モデルで使用されているがまだ特定されていないフィールドが一目でわかるので気に入っていますが、追加したい場合、すべてのドキュメントを更新して新しいスキーマ設計を反映させるのは面倒なようですのような追加のフィールドfavorite_color

ほとんどのベテラン mongodb ユーザーはこれをどのように処理しますか?

4

2 に答える 2

4

2番目のアプローチをお勧めします。

  1. ソース コード内のエンティティ クラスを見れば、常に意図した構造を確認できます。それとも、動的言語を使用し、エンティティを作成しませんか?
  2. null 列名を保存する必要がないため、レコードごとに多くのスペースを節約できます。これは、小さなコレクションでは高くないかもしれません。しかし、何百万ものレコードがある大規模な場合、フィールドの名前を短くすることさえあります。
  3. すでに述べたように。オプションの列名を指定することで、パターンを作成します。これに従う場合は、新しいフィールドを追加するときに既存のすべてのレコードを更新する必要があります。これもまた、大規模な DB にとっては悪い考えです。

いずれにせよ、それはすべてあなたのデータベースサイズを下げます。大量の GB または TB のデータをターゲットにしない場合は、どちらの方法でも問題ありません。ただし、DB が非常に大きくなる可能性があると予測した場合は、サイズを削減するために何でもします。列名にストレージの 30 ~ 40% を使用するのは得策ではありません。

于 2013-01-24T11:45:59.530 に答える
2

私は最初のオプションを好みます。アプリケーション内でコーディングするのが簡単で、物事がどのように機能するかを理解するために必要な状態ホルダーと関数がはるかに少なくて済みます。

時間の経過とともに新しいフィールドを追加する場合、SQL の場合のように、この新しいフィールドをサポートするためにすべてのレコードを更新する必要はありません。新しいフィールドをモデル アプリケーション側に書き込み、このフィールドnullがMongoDB からは返されません。

良い例は PHP です。

user最初はフィールドが1つしかないクラスがありますが、name

class User{
    public $name;
}

6 か月後には 60,000 人のユーザーを追加したいと考えていaddressます。その変数をアプリケーション モデルに追加するだけです。

class User{
    public $name;
    public $address = array();
}

これはnull、SQL に新しいフィールドを追加するのとまったく同じように機能し、オンデマンドですべての行に実際に追加する必要はありません。

これは非常にリアクティブな設計です。必要のないものは更新しないでください。その行が使用される場合は更新されますが、そうでない場合は誰が気にしますか。

したがって、最終的には、行は実際にはオプション 1 と 2 の組み合わせになりますが、実際には反応的なオプション 1 です。

編集

ストレージ側では、ドキュメントの事前割り当てと移動についても考慮する必要があります。

セット レコードの量が現在ドキュメントの 3 分の 1 にすぎないとしますが、突然、ユーザーがすべてのフィールドでドキュメントを更新すると、ドキュメントの移動による余分な断片化が発生します。

通常、このようなスキーマを定義するときは、ほとんどの場合 (SQL スキーマが行うのと同じように) 最終的に成長し、そのユーザーに適用されるスキーマを定義しています。

これは、ストレージが短期的には低くなる可能性がある場合でも、断片化が発生し、その断片化が原因でクエリが遅くなる可能性があり、現在直面している問題のためにcompacts またはsを実行しなければならないことに簡単に気付く可能性があることを考慮する必要があります。repairDb

上で述べたこれらの関数は両方とも、定期的に実行するようには設計されておらず、運用環境で実行するとパフォーマンスに重大な問題があることに注意してください。

したがって、上記の構造を使用すると、すべてのドキュメントに新しいフィールドを追加する必要がなくなり、長期的には移動や問題が少なくなる可能性が高くなります。

2 の累乗サイズのパディングを使用することで、一貫して増大するドキュメントのパフォーマンスの問題を修正できますが、これはコレクション全体であるため、いっぱいになったドキュメントでも以前のスペースの少なくとも 2 倍を使用し、小さなドキュメントはおそらく完全なドキュメントが のパディング係数で持つであろうスペース1

別名、スペースを失うのであって、それを得るのではありません。

于 2013-01-24T11:20:49.393 に答える