Разработка модели данных для версионных данных

Я ищу информацию о наилучшем способе разработки модели данных, основанной на версионных данных. Будут отношения «один ко многим» и «многие ко многим», которые могут меняться от версии к версии.

Я ищу несколько разных стратегий, конечной целью которых является эффективное сравнение и, если возможно, только сохранение дельты.


person binarymelon    schedule 19.10.2012    source источник


Ответы (1)


вступление

На самом деле это достаточно сложная проблема.

Управление версиями объектов легко. Версионных связей между ними не так уж и много — придется принимать некоторые дизайнерские решения. Например:

  • Вам нужно получить «моментальный снимок» всего графика в любой момент истории?
  • Вы хотите безвозвратное удаление или возможность восстановить удаленные объекты и соединения?
  • Вы предпочитаете скорость (и не возражаете копировать весь график между версиями) или пространство?

Кроме того, большинство «вспомогательных» таблиц, вероятно, также должны быть «с учетом версии».

Дизайн

Если бы я был вами, я бы, вероятно, начал свой путь со следующей отправной точки:

введите здесь описание изображения

Символ между ОБЪЕКТОМ и СОЕДИНЕНИЕМ — "категория" (иначе говоря, наследование, подкласс, иерархия обобщения и т. д.).

Основная идея этого дизайна заключается в поддержке функций «моментального снимка», «восстановления» и «дельта»:

  • Весь граф имеет глобальную версию (она же «генерация»), и мы храним только дельты между ними.
  • Каждый объект имеет версию с этим глобальным поколением (в отличие от локальных, специфичных для объекта версий).
  • Соединения являются объектами, что также делает их версионными.
  • Every time a set of objects enters the repository, a new GENERATION is inserted and:
    • An inserted object is inserted into OBJECT and OBJECT_VERSION.
    • Измененный объект вставляется в OBJECT_VERSION.
    • Удаленный объект вставляется в OBJECT_VERSION с DELETED = true.
    • Восстановленный объект вставляется в OBJECT_VERSION с DELETED = false. Кстати, это позволяет многократно повторять цикл удаления/восстановления.
    • Остальные объекты остаются нетронутыми, поэтому мы не тратим место на копирование неизмененных данных.
  • Соединение не может быть изменено. Чтобы «переместить» дочерние объекты в новый родитель, удалите старое соединение (путем установки DELETED, как описано выше) и вставьте новое. На самом деле удаление — это единственный вид модификации, поддерживаемый соединением.

Запрос будет выглядеть примерно так:

  • Чтобы получить один объект, из всех его версий выберите самую старшую, которая еще не выше желаемого поколения. Если DELETED этой версии имеет значение true, объект отсутствует в этом поколении.
  • Чтобы получить снимок всего графа в нужном поколении, выполните описанное выше для всех объектов и создайте граф в памяти. Удалите соединения, одна или обе конечные точки которых УДАЛЕНЫ.
  • Чтобы получить объекты, связанные с данным объектом, рекурсивно пройдите по СОЕДИНЕНИЮ, но прервите рекурсию, как только вы встретите объект, который не соответствует указанным выше критериям.

Пример

Допустим, вам нужно поместить объекты A, B и C, где A является родительским для B и C:

generation: 0

      A0
     /  \
   B0    C0

Добавить новый объект D:

generation: 0 1

      A0
     / | \
   B0  C0 D1

Измените A и C и удалите B:

generation: 0 1 2

      A0
      A2
     / | \
   B0  C0 D1
   B2* C2

   (*) OBJECT_VERSION.DELETED is true

Переместите C из A в D:

generation: 0 1 2 3

      A0
      A2
     / |* \
   B0  C0  D1
   B2* C2  |
           C3

И т.д...

Некоторые размышления

Этот дизайн открыт для аномалий с непоследовательными удалениями: база данных не будет защищаться от соединения удаленного и неудаленного объекта или перевода одного из объектов в удаленное состояние без удаления соединения. Вы не узнаете, действительно ли соединение, пока не проверите обе конечные точки. Если ваши данные иерархичны, вместо этого вы можете использовать «модель достижимости»: объект не удаляется, если к нему можно получить доступ из какого-либо корневого объекта. Вы никогда не удаляете объект напрямую — вы просто удаляете все связи с ним. Это может хорошо работать для иерархий, таких как папки/файлы и т.п., где вы начинаете «сверху» и ищете снизу, пока не достигнете желаемого объекта (объектов).

Альтернативой «неизменяемым» соединениям является наследование CONNECTION_VERSION от OBJECT_VERSION и размещение там PARENT_ID/CHILD_ID с использованием идентифицирующих отношений для обеспечения правильной зависимости ромбовидной формы. смоделирован. Это может быть полезно, если вам нужно отслеживать историю ходов.

Это, конечно, общие штрихи, надеюсь, вы найдете свой путь...

person Branko Dimitrijevic    schedule 19.10.2012
comment
Версии существуют независимо друг от друга. Возможно, версия — плохой термин для использования. Это скорее иерархия родитель/потомок. - person binarymelon; 20.10.2012