変更を追跡する必要があるプロジェクトのドキュメントストアデータベースを試すことを考えています。 Firebaseでプロトタイプを作成したいのですが、スキーマ/実装はMongoDbでも同じだと思います
(簡略化された)設定では、3つのテーブル/コレクションProject
、Asset
およびUser
があります。 (ログイン済み)User
は、Project
またはAsset
を変更(作成、更新、または削除)できます。 Asset
は(最大1つ)Project
に割り当てることができます。
Asset
またはProject
に変更が加えられたときはいつでも、変更を加えたUser
を、いつ行ったか、そしてほとんどの場合、以前の状態。
プロジェクトおよびアセットドキュメントにWrittenWhen
、WrittenBy
およびIsActive
の3つの属性を追加します。これらを「実際の」データに入力します。
レコードが変更されるとそれをコピーしますが、IsActiveフラグを反転させます。 WrittenWhen
およびWrittenBy
の元の値を保持します。元のレコードは、修正されたユーザーのIDとタイムスタンプで更新されます。私はこのようにして、このレコードのマジックIDを保持する他のレコードがそのポインタを保持するようにします。
読み取り時のみ、IsActiveの正しい値を持つレコードを探します。
IsActiveは、アーカイブレコードが別のコレクション/名前空間/データベース/テクノロジーがサポートするものに書き込まれている場合は省略できます。
マイケル、私がこの実装に関して持っているカップルの懸念に感謝します。サイズ-これには多くの冗長データが含まれている可能性があり、おそらく必要なデータの100倍以上が格納されます。mongodbを使用する多くのデプロイメントでは、これは問題ではない可能性がありますが、BaaSのようなFirebaseの場合、これにより、大きな違い。私のもう1つの懸念は、以前と比較し、複数のユーザーが複数のデータポイントを編集する可能性がある場合を除いて、どのデータポイントが編集されたかがわからないことです。「最終更新者* on * "多くの古いレコードの検索が必要な場合があります– Daniel Mar 10 at 16:16
集めたポイントは有効です。別の設計では、変更された値のみを履歴ストアに格納します。その場合、レコードは(主キーフィールド、変更されたフィールドの名前、古い値、新しい値、作成者、作成時期)になります。変更されたパーツのみを保存すると、2つの新しい問題が直接発生します。
1つは、必要になるまで差分コストを据え置くのではなく、変更された部分を書き込みごとに分離するという必須のオーバーヘッドがあります。通常、OLTP書き込みは高速であり、監査レポートはパフォーマンスにとって重要ではありません。したがって、レポートが必要な場合にその作業を延期することは理にかなっているように思われます。もちろん、レコード全体は、短い差分のみのレコードを書き込むだけではありません。インフラストラクチャをベンチマークして、それが重要かどうかを確認できます。
2つ目は、デルタのみを保存することで、変更が発生したデータコンテキストを失うことです。つまり、デルタを格納するだけで、単一の監査レコードを読み取って、たとえばフィールド53が「A」から「B」に変更されたことを確認できます。その変更が発生したとき、他のすべてのフィールドにはどのような値がありましたか?調べるには、関心のある他のフィールドの最新の値が見つかるまで、履歴をさかのぼって読む必要があります。繰り返しますが、これがシナリオの有効なユースケースであるかどうか、または変更頻度と監査読み取り頻度が問題になるかどうかはわかりませんが、検討する価値があります。
どちらの方式でも「最後に更新された.. on ..」を表示するには、両方の方法でこの情報をすべての履歴レコードに保存するため、書き込まれた最後の履歴レコードの単一レコードルックアップです。保存された完全なレコードで変更されたwhatを見つけるには、2回目の読み取りと差分が必要ですが、これはデルタストアでは必要ありません。履歴レコードを再構築することは、完全なレコードでは簡単な作業であり、デルタでは処理負荷が高くなります。
1つの設計を他の設計に対して完全に評価するのに十分なほど、要件や制約がわかりません。私の好みは、実装の容易さと(可能性が高い)パフォーマンスのために、私が文書化したものを好みます。ただし、無料のランチはありません。作業はいつかどこかで行われる必要があります。