Domanda

sto cercando in attuazione oggetto delle versioni con il tocco aggiunto di aver bisogno di avere entrambi gli oggetti dal vivo e progetti, e potrebbe utilizzare le intuizioni dall'esperienza qualcuno in questo, come sto cominciando a chiedersi se è ancora possibile senza potenzialmente hack orribili.

ti rompo il basso per i messaggi con tag per il bene di questo esempio, ma il mio caso d'uso è un po 'più generale (che coinvolge le dimensioni che cambiano lentamente - http://en.wikipedia.org/wiki/Slowly_changing_dimension ).

Supponiamo che hai un tavolo i messaggi, una tabella di tag, e un tavolo post2tag:

posts (
 id
)

tags (
 id
)

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

Ho bisogno di un paio di cose:

  1. Essere in grado di mostrare esattamente come un post sembrava ad un datetime arbitraria, anche per le righe eliminate.
  2. tenere traccia di chi sta modificando ciò che, per una pista di controllo completa.
  3. bisogno di una serie di viste materializzate (tavole "live") per ragioni di mantenere l'integrità referenziale (cioè la registrazione dovrebbe essere trasparente per gli sviluppatori).
  4. deve essere opportunamente veloce per vivere e l'ultima bozza righe.
  5. Essere in grado di avere una bozza di posta coesistono con un post dal vivo.

Sto indagando varie opzioni. Finora, il migliore che è venuta in mente (senza punti di # 4 / # 5) sembra un po 'come la messa a punto type6-ibrido SCD, ma invece di avere un valore booleano corrente c'è una vista materializzata per la riga corrente. Per tutti gli effetti, sembra che questo:

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)
)

sto usando pg_temporal per mantenere gli indici sul periodo (created_at, deleted_at). E io continuo le varie tabelle in sincronia con i trigger. Bla bla bla ... ho creato i trigger che consentono di annullare una modifica di messaggi / tag in modo tale che il progetto viene memorizzato nei giri senza essere pubblicato. E le grandi opere.

ad eccezione di , quando ho bisogno di preoccuparsi per i rapporti correlati progetto fila su post2tag. In tal caso, si scatena l'inferno, e questo suggerimenti per me che ho un qualche tipo di problema di progettazione in là. Ma io sono a corto di idee ...

Ho considerato l'introduzione di duplicazione dei dati (ovvero n righe post2tag introdotte per ogni progetto di revisione). Questo tipo di opere, ma tende ad essere molto più lento di quanto mi piacerebbe che fosse.

Ho considerato l'introduzione di bozze tabelle per l ' "ultima bozza", ma questo tende rapidamente a diventare molto molto brutto.

Ho considerato tutti i tipi di bandiere ...

Quindi domanda: c'è un mezzo generalmente accettati di gestione diretta vs righe non vivere in un ambiente controllato fila versione? E se no, che cosa hai provato e stato ragionevolmente di successo con?

È stato utile?

Soluzione 4

Credo di inchiodato. In sostanza, si aggiunge un (unico) progetto campo per le relative tabelle, e si lavora sui progetti come se fossero un nuovo post / tag / etc.

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)
)

Altri suggerimenti

Anchor modellazione è un bel modo per implementare un temporale dB - vedere la articolo di Wikipedia anche. Richiede un certo tempo per abituarsi, ma il lavoro bello. C'è un strumento di modellazione in linea e se si carica il file XML in dotazione [File -> Load Model from Local File] si dovrebbe vedere qualcosa di simile -. utilizzare anche [Layout --> Togle Names]

entrare descrizione dell'immagine qui

Il [Generate --> SQL Code] produrrà DDL per le tabelle, viste e funzioni point-in-time. Il codice è piuttosto lungo, quindi non sto postando qui. Controllare il codice out - potrebbe essere necessario modificarlo per il vostro DB.

Ecco il file da caricare in strumento di modellazione.

<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>

Ho implementato un database temporale utilizzando SCD di tipo 2 e le regole PostgreSQL e trigger, lo avvolse in un pacchetto autonomo per ActiveRecord: http://github.com/ifad/chronomodel

Il design è indipendente dal linguaggio / framework, anche se - è possibile creare regole e trigger manualmente e il database si prenderà cura di tutto il resto. Dai un'occhiata alla https://github.com/ifad/chronomodel/blob/master /README.sql .

Anche l'indicizzazione e interrogazione di dati temporali utilizzando gli operatori geometrici efficiente è incluso come bonus. : -)

post2tag_revs ha un problema in quanto sta cercando di esprimere 2 concetti fondamentalmente diversi.

Un tag applicato ad un progetto di messaggio di revisione sempre e solo vale per quella revisione, a meno che la revisione viene mai pubblicato.

Una volta che un tag viene pubblicato (cioè associata ad una revisione post pubblicato), si applica a ogni futura revisione del post fino a quando non è stato revocato.

E l'associazione con una revisione pubblicato, o unasociating, non è necessariamente simultaneo con la revisione in corso di pubblicazione, a meno che non far rispettare artificialmente questo clonando una revisione solo così è possibile associare dei tag aggiunte o rimozioni ...

mi piacerebbe cambiare il modello facendo post2tag_revs.post_rev rilevante solo per i progetti di tag. Una volta che la revisione è pubblicato (e il tag è vivo), userei una colonna timestamp per segnare l'inizio e la fine della validità pubblicato. Si può o non può decidere una nuova voce post2tag_revs per rappresentare questo cambiamento.

Come fai notare, questo rende questo rapporto bi-temporale . Si potrebbe migliorare le prestazioni nel caso "normale" con l'aggiunta di un valore booleano per post2tag per indicare che il tag è attualmente associato con il post.

Utilizzare solo 3 tavoli:. Messaggi, tag e post2tag

colonne

Add start_time e END_TIME a tutte le tabelle. Aggiungere indice univoco per la chiave, start_time e end_time. Aggiungere indice univoco per la chiave in cui end_time è nullo. Aggiungere trigers.

Per la corrente:

SELECT ... WHERE end_time IS NULL

Al momento:

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

Ricerca dei dati attuali non è lento a causa di indice funzionale.

Modifica:

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top