質問

ライブオブジェクトとドラフトオブジェクトの両方を持つ必要があるという追加のひねりを加えてオブジェクトバージョンを実装することを検討しています。これで誰かの経験からの洞察を使用することができます。

例のためにタグのある投稿に分解しますが、私のユースケースはもう少し一般的です(ゆっくりと変化する寸法が含まれます - http://en.wikipedia.org/wiki/slowly_changing_dimension).

投稿テーブル、タグテーブル、およびポスト2TAGテーブルを使用してください。

posts (
 id
)

tags (
 id
)

post2tag (
 post_id fkey posts(id),
 tag_id fkey tags(id)
)

私はいくつかのことが必要です:

  1. 削除された行を含む、任意のdateTimeで投稿がどのように見えるかを正確に示すことができます。
  2. 完全な監査証跡のために、誰が何を編集しているかを追跡します。
  3. 参照的な整合性を維持するために、一連の具体化されたビュー(「ライブ」テーブル)が必要です(つまり、ロギングは開発者に透過的でなければなりません)。
  4. ライブに適切に速くする必要があります 最新のドラフト行。
  5. ライブポストとドラフトポストを共存できるようになりました。

私はさまざまなオプションを調査してきました。これまでのところ、(ポイント#4/#5なしで)私が思いついた最高のものは、SCD Type6-Hybridのセットアップに少し似ていますが、現在のブール値を使用する代わりに、現在の行の具体的なビューがあります。すべての意図と目的のために、それは次のように見えます:

posts (
 id pkey,
 public,
 created_at,
 updated_at,
 updated_by
)

post_revs (
 id,
 rev pkey,
 public,
 created_at,
 created_by,
 deleted_at
)

tags (
 id pkey,
 public,
 created_at,
 updated_at,
 updated_by
)


tag_revs (
 id,
 public,
 rev pkey,
 created_at,
 created_by,
 deleted_at
)

post2tag (
 post_id fkey posts(id),
 tag_id fkey tags(id),
 public,
 created_at,
 updated_at,
 updated_by
)

post2tag_revs (
 post_id,
 tag_id,
 post_rev fkey post_revs(rev), -- the rev when the relation started
 tag_rev fkey tag_revs(rev), -- the rev when the relation started
 public,
 created_at,
 created_by,
 deleted_at,
 pkey (post_rev, tag_rev)
)

PG_TEMPORALを使用して、期間(created_at、deleted_at)でインデックスを維持しています。そして、トリガーを使用してさまざまなテーブルを同期させます。 Yada Yada Yada ...私は、ドラフトが公開されずにRevに保存されるように、投稿/タグへの編集をキャンセルできるトリガーを作成しました。それはうまく機能します。

を除外する Post2TAGでのドラフト列関連の関係について心配する必要がある場合。その場合、すべての地獄が解き放たれ、これは私にとって、私がそこにある種のデザインの問題を示唆しています。しかし、私はアイデアが不足しています...

私は、データの複製を導入することを検討しました(ドラフトの改訂ごとに導入された2TAG後の行があります)。この種の動作ですが、私が望んでいるよりもずっと遅くなる傾向があります。

「最後のドラフト」にドラフトテーブルを導入することを検討しましたが、これはすぐに非常にugいものになる傾向があります。

私はあらゆる種類の旗を考えました...

質問:連続したバージョン制御環境でライブと非ライブの行を管理する一般的に受け入れられている手段はありますか?そうでない場合、あなたは何を試して、合理的に成功しましたか?

役に立ちましたか?

解決 4

私はそれを釘付けにしたと思います。基本的に、関連するテーブルに(一意の)ドラフトフィールドを追加し、ドラフトで新しい投稿/タグなどのように作業します。

posts (
 id pkey,
 public,
 created_at stamptz,
 updated_at stamptz,
 updated_by int,
 draft int fkey posts (id) unique
)

post_revs (
 id,
 public,
 created_at,
 created_by,
 deleted_at,
 pkey (id, created_at)
)

tags (
 id pkey,
 public,
 created_at,
 updated_at,
 updated_by,
 draft fkey tags (id) unique
)


tag_revs (
 id,
 public,
 created_at,
 created_by,
 deleted_at,
 pkey (id, created_at)
)

post2tag (
 post_id fkey posts(id),
 tag_id fkey tags(id),
 public,
 created_at,
 updated_at,
 updated_by,
 pkey (post_id, tag_id)
)

post2tag_revs (
 post_id,
 tag_id,
 public,
 created_at,
 created_by,
 deleted_at,
 pkey (post_id, tag_id, created_at)
)

他のヒント

アンカーモデリング 時間的なDBを実装する良い方法です - を参照してください ウィキペディアの記事 それも。慣れるのに時間がかかりますが、うまくいきます。あります オンラインモデリングツール 付属のXMLファイルをロードする場合 [File -> Load Model from Local File]このようなものが表示されるはずです - も使用してください [Layout --> Togle Names].

enter image description here

[Generate --> SQL Code] テーブル、ビュー、ポイントインタイム関数用のDDLを生成します。コードはかなり長いので、ここに投稿していません。コードを確認してください - DBのためにそれを変更する必要があるかもしれません。

モデリングツールにロードするファイルは次のとおりです。

<schema>
<knot mnemonic="EXP" descriptor="Expired" identity="smallint" dataRange="char(1)">
<identity generator="true"/>
<layout x="713.96" y="511.22" fixed="true"/>
</knot>
<anchor mnemonic="US" descriptor="User" identity="int">
<identity generator="true"/>
<attribute mnemonic="USN" descriptor="UserName" dataRange="varchar(32)">
<layout x="923.38" y="206.54" fixed="true"/>
</attribute>
<layout x="891.00" y="242.00" fixed="true"/>
</anchor>
<anchor mnemonic="PO" descriptor="Post" identity="int">
<identity generator="true"/>
<attribute mnemonic="TIT" descriptor="Title" dataRange="varchar(2)">
<layout x="828.00" y="562.00" fixed="true"/>
</attribute>
<layout x="855.00" y="471.00" fixed="true"/>
</anchor>
<anchor mnemonic="TG" descriptor="Tag" identity="int">
<identity generator="true"/>
<attribute mnemonic="TGT" descriptor="TagText" dataRange="varchar(32)">
<layout x="551.26" y="331.69" fixed="true"/>
</attribute>
<layout x="637.29" y="263.43" fixed="true"/>
</anchor>
<anchor mnemonic="BO" descriptor="Body" identity="int">
<identity generator="true"/>
<attribute mnemonic="BOT" descriptor="BodyText" dataRange="varchar(max)">
<layout x="1161.00" y="491.00" fixed="true"/>
</attribute>
<layout x="1052.00" y="465.00" fixed="true"/>
</anchor>
<tie timeRange="datetime">
<anchorRole role="IsTagged" type="PO" identifier="true"/>
<anchorRole role="IsAttached" type="TG" identifier="true"/>
<anchorRole role="BYAuthor" type="US" identifier="false"/>
<knotRole role="Until" type="EXP" identifier="false"/>
<layout x="722.00" y="397.00" fixed="true"/>
</tie>
<tie timeRange="datetime">
<anchorRole role="Contains" type="PO" identifier="true"/>
<anchorRole role="ContainedIn" type="BO" identifier="false"/>
<layout x="975.00" y="576.00" fixed="true"/>
</tie>
<tie>
<anchorRole role="CreatedBy" type="TG" identifier="true"/>
<anchorRole role="Author" type="US" identifier="false"/>
<layout x="755.10" y="195.17" fixed="true"/>
</tie>
<tie>
<anchorRole role="CreatedBy" type="PO" identifier="true"/>
<anchorRole role="Author" type="US" identifier="false"/>
<layout x="890.69" y="369.09" fixed="true"/>
</tie>
<tie>
<anchorRole role="ModifiedBy" type="BO" identifier="true"/>
<anchorRole role="Author" type="US" identifier="false"/>
<layout x="1061.81" y="322.34" fixed="true"/>
</tie>
</schema>

SCD Type 2およびPostgreSQLルールとトリガーを使用して時間的なデータベースを実装し、ActiveRecordの自己完結型パッケージにラップしました。 http://github.com/ifad/chronomodel

ただし、このデザインは言語 /フレームワークから独立しています。ルールを手動で作成してトリガーすることができ、データベースは残りを処理します。見て https://github.com/ifad/chronomodel/blob/master/readme.sql.

また、幾何学的演算子を使用した時間データの効率的なインデックス作成とクエリもボーナスとして含まれています。 :-)

Post2Tag_Revsには、2つの根本的に異なる概念を表現しようとしているという点で問題があります。

ドラフト後の改訂に適用されるタグは、改訂が公開されていない限り、その1つの改訂にのみ適用されます。

タグが公開されると(つまり、公開された投稿改訂に関連付けられています)、取り消されるまで投稿のすべての将来の改訂に適用されます。

公開された改訂版、またはそれに関連しないことに関連することは、タグの追加や削除を関連付けることができるように、リビジョンをクローニングすることで人為的にこれを実施しない限り、改訂が公開されるのと必ずしも同時はありません...

Post2tag_revs.post_revをドラフトタグにのみ関連させることにより、モデルを変更します。リビジョンが公開されたら(およびタグがライブ)、タイムスタンプ列を使用して、公開された有効性の開始と終了をマークします。新しいPost2TAG_REVSエントリがこの変更を表すことを望んでいる場合としない場合があります。

あなたが指摘するように、これはこの関係になります バイテンポラル. 。 Post2TAGにブール値を追加して、タグが現在投稿に関連付けられていることを示すことにより、「通常の」ケースのパフォーマンスを改善する場合があります。

3つのテーブルのみを使用します:投稿、タグ、Post2Tag。

start_timeとend_time列をすべてのテーブルに追加します。キー、start_time、end_timeの一意のインデックスを追加します。 end_timeがnullであるキーに一意のインデックスを追加します。トリガーを追加します。

現在の場合:

SELECT ... WHERE end_time IS NULL

当時の:

WHERE (SELECT CASE WHEN end_time IS NULL
THEN (start_time <= at_time)
ELSE (start_time <= at_time AND end_time > at_time)
END)

機能的なインデックスのため、現在のデータの検索は遅くありません。

編集:

CREATE UNIQUE INDEX ... ON post2tag (post_id, tag_id) WHERE end_time IS NULL;
CREATE UNIQUE INDEX ... ON post2tag (post_id, tag_id, start_time, end_time);

FOREIGN KEY (post_id, start_time, end_time) REFERENCES posts (post_id, start_time, end_time) ON DELETE CASCADE ON UPDATE CASCADE;
FOREIGN KEY (tag_id, start_time, end_time) REFERENCES tags (tag_id, start_time, end_time) ON DELETE CASCADE ON UPDATE CASCADE;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top