web-dev-qa-db-ja.com

CRUD以外のアプローチの例はありますか?

私はプログラマーですが、アーキビストとしても働いています。アーキビストとして、それはデータを保持することについて多くのことです。

データの操作に関しては、同僚とよく議論します。 CRUDのUとDはあまり好きではありません。むしろ、私は新しいレコードを追加し、古いレコードへの参照を持つことを好むレコードを更新します。このようにして、変更の履歴を作成します。また、レコードを削除するのは好きではなく、非アクティブとしてマークします。

これに用語はありますか?基本的にデータの作成と読み取りのみですか?このアプローチの例はありますか?

14
Pieter B

レコードを削除済みとしてマークすることは soft-deleting として知られています。更新のための別のフレーズを聞いたことがありませんが、それが原因で古いレコードをソフト削除して、新しいレコードを作成したと思います。

これは議論の余地のあるテクニックです。リンクを参照してください: Con vs Pro

16
pdr

変更履歴を保持する際の問題の1つは、データベースが乱雑になり、サイズが劇的に大きくなる可能性があることです(使用パターンによって異なります)。そのため、監査証跡を別の場所に保存し、実際のアプリケーションテーブルに関連データのみを入力しておくことをお勧めします。そのため、アプリケーションによってCRUD操作が実行されるたびに、変更が監査テーブルに記録され、CRUD操作がアプリケーションテーブルに対して実行されます(ソフト削除は行われません)。

監査証跡を個別に保持することで、アプリケーションが操作できる初期のデータストアを提供し、必要に応じて変更履歴を保持できます。また、ビジネス要件に応じて、監査証跡を個別にアーカイブしたり、破棄したりすることもできます。

11
System Down

EventSourcing 探しているパターンのように聞こえます。

の色を追跡したい単純な "car"オブジェクトを使用した例を考えてみましょう(擬似C#コードが続きます)。

public class Car {
  public string Color { get; set; }
  public Car() { this.Color = "Blue"; }
}

CRUD実装では、車の色を更新すると、以前の色が失われます。

MyCar.Color = "Red";
MyCar.Save();  // Persist the update to the database and lose the previous data

この情報の損失は、あなたが最も避けたいことのように聞こえます(したがって、CRUDパターンの更新と削除の部分が嫌いです)。

変更を更新するときにイベントに応答するようにcarクラスを書き直すと、次のようになります。

public class Car {
    public string Color { get; private set; } // Cannot be set from outside the class

    public void ApplyEvent(CarColorChangedEvent e) {
      this.Color = e.Color;
    }
}

では、このオブジェクトの色をどのように更新しますか? CarColorChangedイベントを作成できます!

var evnt = new CarColorChangedEvent("Red");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

実際のモデルオブジェクトの保存がないことに注意してください。これは、モデルを直接永続化する代わりに、モデルを現在の状態にするイベントを永続化するためです。これらのイベントは immutable である必要があります。

早送りして、色をさらに数回変更してみましょう。

var evnt = new CarColorChangedEvent("Green");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

var evnt = new CarColorChangedEvent("Purple");
MyEventStore.save(evnt);
MyCar.ApplyEvent(evnt);

イベントストレージ(リレーションデータベース、ファイルベースなど)を見ると、車オブジェクトに関連する一連のイベントが表示されます。

CarColorChangedEvent => Red
CarColorChangedEvent => Green
CarColorChangedEvent => Purple

その自動車オブジェクトを再構築したい場合は、新しい自動車オブジェクトを作成し、イベントストアからのイベントを上記のオブジェクトに適用するだけで作成できます。

var MyCar = new Car();
var events = MyDatabase.SelectEventsForCar("CarIdentifierHere");
foreach(var e in events) {
  MyCar.ApplyEvent(e);
}
Console.WriteLine(MyCar.Color); // Purple

イベントのストリームを使用して、新しい自動車オブジェクトを作成し、必要なイベントのみを適用するだけで、自動車の状態を前の期間にロールバックできます。

var MyCar = new Car();
var event = MyDatabase.GetFirstEventForCar("CarIdentifierHere");
MyCar.ApplyEvent(e);
Console.WriteLine(MyCar.Color); // Red
5
Mike

イベントソーシングはそのための方法であり、グレッグヤングがそれについて語っていることを確認する必要があります。

http://goodenoughsoftware.net/

彼のデータベース(イベントストア)でこのプレゼンテーションもご覧ください。他のビデオも見つけることができます。

http://oredev.org/2012/sessions/a-deep-look-into-the-event-store

削除されたアイテムを検索できるようにする必要がある場合を除いて、「ソフト削除」の回答は求めませんが、削除されたと考えるべきではなく、アーカイブされていると考えるべきです。ここでは用語が非常に重要だと思います。

「バージョンテーブル」も維持したくありません。私が今まで見たすべての「バージョンテーブル」(現時点でクリーンアップしようとしているものを含む-バグのために7年間のデータが破損しています...そしてそれを取得する方法はありません過去のデータがあっても戻ってきます...それは同じように破損しているためです)コードのバグが原因で破損し、最終的には元に戻せないためにデータが失われますそして、破損がめちゃくちゃになったデータを再作成します。

イベントソーシングモデルでは、これは当てはまりません。ユーザーがしたことをいつでも正確に再生できます。これは、CRUDとイベントソーシングの非常に重要な違いです。イベントソーシングアーキテクチャは、データストアやドメインモデルオブジェクトではなく、イベントストアにイベントを保存します。イベントは複数のオブジェクトに簡単に影響を与える可能性があります。ショッピングカートの各アイテムを実際の注文に変換するショッピングカートソリューションを考えてみてください。 1つのイベントは、すべてのアイテムオブジェクトと、注文オブジェクトに変換されるショッピングカートオブジェクトに影響を与えます。

データベース内のすべてのテーブルの各行のバージョン付きコピーを保持している場合は、特定のタイムスタンプまで巻き戻す必要があるという恐ろしいことを想像してください。そのバージョンテーブルを維持するための非常に多くのスペースとパフォーマンスオーバーヘッドは言うまでもありません。

イベントソーシングを使用すると、特定の時点までイベントを再生するだけで、簡単に巻き戻すことができます。スナップショットを使用して早送りを行うことができますが、それはすべて実装の問題です。

しかし、データを失わないことに特に関心があるので、あなたが好きだと思う本当の利点は、このデータを保存するコードにバグを発見した場合、戻ってデータをクリーンアップする必要がないことです。 (データが完全ではないため、これはしばしば不可能です)。代わりに、バグを修正し、すべてのイベントを再生します。次に、ニースの正しいデータを含むデータベースがあります。

デバッグの場合、どのくらいの頻度でユーザーに何をしたかをユーザーに尋ねましたか?なぜ彼らがしたことを再生してからコードをステップ実行しないのですか?かなり気の利いたね。

お役に立てれば。

5
Jay Pete

はい、エンタープライズシステムでは非常に一般的ですが、基本的に2つのアプローチがあります。

  • 「bi-一時的」で、すべてのレコードに有効開始日時と有効終了日時のスタンプがあります(「現在」レコードの有効期限は「永久」-null、「9999-12-31」またはそのような高い値)。レコードが削除されることはなく、「有効期限」の日付が現在の時刻に設定されます。更新の場合、新しいレコードは、現在の時刻の有効な日付と永久に有効な日付で挿入されます。
  • 「履歴テーブル」-レコードが変更されるたびに、古いレコードのコピーがイベントのタイムスタンプとともに履歴/ログテーブルにダンプされます。

どちらの方法でも、粒度には大きなばらつきがあります。例えば注文アイテムのウィジェットの数量が変更された場合、注文全体またはその1つのアイテムの履歴を維持しますか?

一般的に言って、「バイテンポラル」は多くの追加作業であり、「12月31日の時点でオーディターが注文ステータスを取得する」のような多くのユースケースがある場合にのみ価値があります。

2
James Anderson

正確にはあなたの例ではありませんが、古い金融システムでは [〜#〜] worm [〜#〜] ストレージがありました。 「更新」する必要がある場合は、新しいレコードを作成し、最後のレコードを常に現在のレコードとして参照しましたが、コミットされたデータを上書きすることはできませんでした。

多くの人々がその考えを後のシステムに持ち込んだ。あなたがWORMテーブルと呼んでいる説明を聞いたことがありますが、これらのサークルでのみです。

2
Bill

"soft-deletes" pdrが示唆するように を使用できます。更新に関しては、ここで私の答えのようなレコードの履歴を保持できます: https://dba.stackexchange.com/questions/28195/save-history-editable-data-rdbms/28201#28201 OPが特定の種類のデータのすべてのバージョンを追跡できるようにしたい場合。