6

非常によくある設計上の問題があります。Google App Engine のレコードの履歴ログ (監査証跡) を実装する必要があります。履歴ログは構造化する必要があります。つまり、すべての変更を自由形式のテキストに結合して文字列フィールドに保存することはできません。

履歴モデルについて次のオプションを検討しましたが、オプション #1 のパフォーマンスの問題に気付いた後、オプション #3 を実装することにしました。しかし、このソリューションが効率的でスケーラブルかどうかについてはまだ疑問があります。たとえば、オプション #3 で動的プロパティの数が増えると、パフォーマンスが大幅に低下するリスクはありますか?

各オプションの長所と短所について詳しい知識はありますか? または、Google App Engine DB の特性に適用できる他の監査証跡の設計パターンを提案できますか?

  1. 従来の SQL の「マスター詳細」関係を使用する
    • 長所
      • SQL のバックグラウンドを持つデータベース開発者にとって理解しやすい
      • clean: 履歴レコードとそのプロパティの直接定義
      • 検索性能: 履歴から簡単に検索 (インデックスを使用できます)
      • トラブルシューティング: 管理ツール (_ah/admin) による簡単なアクセス
    • 短所
      • 多くの場合、GAE DB でこのように 1 対多の関係を実装することは推奨されません。
      • 読み取りパフォーマンス: 長い監査証跡を表示するための過剰な数のレコード読み取り操作 (たとえば、大きなレコード リストの詳細ペイン)。
  2. 履歴を BLOB フィールドに保存する (ピクルされた python 構造)
    • 長所
      • 実装が簡単で柔軟
      • 読み取りパフォーマンス: 非常に効率的
    • 短所
      • クエリのパフォーマンス: インデックスを使用して検索できません
      • トラブルシューティング: 管理者データベース ビューア (_ah/admin) でデータを検査できない
      • 不潔: SQL 開発者にとって理解/受け入れが容易ではありません (彼らはこれを醜いと考えています)。
  3. Expando の動的プロパティに履歴を保存します。たとえば、フィールドごとにフィールドfieldNameを作成しhistory_fieldName_nます (n=<0..N> は履歴レコードの数です)。
    • 長所:
      • シンプル:実装と理解が簡単
      • トラブルシューティング: 管理インターフェイスからすべての履歴プロパティを読み取ることができます
      • 読み取りパフォーマンス: レコードを取得するための 1 回の読み取り操作
    • 短所:
      • 検索パフォーマンス: 履歴レコードを単純に検索することはできません (名前が異なります)
      • きれいすぎない: プロパティの数は一見すると混乱する可能性があります
  4. メイン レコードのリスト フィールドのセットに履歴を保存します。例えば。リストフィールド をfieldName作成するfieldName_history
    • 長所:
      • clean: 履歴プロパティの直接定義
      • シンプル: SQL 開発者にとって理解しやすい
      • 読み取りパフォーマンス: レコードを取得するための 1 回の読み取り操作
    • 短所:
      • 検索パフォーマンス: 常に何らかの値を持つレコードのみをインデックスを使用して検索でき、特定の時間に値の組み合わせを持つレコードを検索することはできません。
      • トラブルシューティング: admin db viewer でリストを検査するのが難しい
4

1 に答える 1

3

選択しなければならない場合は、オプション 1 を選択します。読み取りは、他のオプションと同等 (またはそれ以上) のパフォーマンスです。また、他のすべてのオプションは、特定の状況 (小規模または非常に大規模な変更セット) でのみ速度の利点があります。また、x 日後に履歴を消去したり、さまざまなモデル タイプ間で履歴をクエリしたりするなど、多くの柔軟性を (より簡単に) 得ることができます。一貫性を保証するために、履歴エンティティを同じトランザクション内の変更されたエンティティの子として作成してください。次のいずれかになる可能性があります。

class HistoryEventFieldLevel(db.Model):
    # parent, you don't have to define this
    date = db.DateTime()
    model = db.StringProperty()
    property = db.StringProperty() # Name of changed property
    action = db.EnumProperty(['insert', 'update', 'delete'])
    old = db.PickleProperty() # Old value for field, empty on insert
    new = db.PickleProperty() # New value for field, empty on delete

class HistoryEventModelLevel(db.Model):
    # parent, you don't have to define this
    date = db.DateTime()
    model = db.StringProperty()
    action = db.EnumProperty(['insert', 'update', 'delete'])
    change = db.PickleProperty() # Dictionary with changed fields as keys and tuples (old value, new value) as values
于 2010-12-11T21:40:14.967 に答える