База данных - Управление версиями данных (продолжение) - PullRequest
5 голосов
/ 26 мая 2009

Мой оригинальный вопрос можно найти здесь , на который я получил несколько отличных ответов, идей и советов.

В рамках исследования осуществимости и производительности я начал преобразовывать свои схемы для того, чтобы версионировать свои данные, используя эти идеи. При этом у меня возникла какая-то другая проблема.

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

Итак, теперь мои данные становятся:

Person
------------------------------------------------
ID                UINT NOT NULL,
NameID            UINT NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL

PersonAudit
------------------------------------------------
ID                UINT NOT NULL,
NameID            UINT NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL,
UserID            UINT NOT NULL,         -- Who
PersonID          UINT NOT NULL,         -- What
AffectedOn        DATE NOT NULL,         -- When
Comment           VARCHAR(500) NOT NULL  -- Why

Name
------------------------------------------------
ID                UINT NOT NULL,
FirstName         VARCHAR(200) NOT NULL,
LastName          VARCHAR(200) NOT NULL,
NickName          VARCHAR(200) NOT NULL

NameAudit
------------------------------------------------
ID                UINT NOT NULL,
FirstName         VARCHAR(200) NOT NULL,
LastName          VARCHAR(200) NOT NULL,
NickName          VARCHAR(200) NOT NULL,
UserID            UINT NOT NULL,         -- Who
NameID            UINT NOT NULL,         -- What
AffectedOn        DATE NOT NULL,         -- When
Comment           VARCHAR(500) NOT NULL  -- Why

В графическом интерфейсе мы могли видеть следующую форму:

ID            :  89213483
First Name    :  Firsty
Last Name     :  Lasty
Nick Name     :  Nicky
Date of Birth :  January 20th, 2005
Email Address :  my.email@host.com

Можно изменить:

  1. Только для части 'name'
  2. Только для части "человек"
  3. Как для имени, так и для личности

Если возникает «1», мы копируем исходную запись в NameAudit и обновляем нашу запись Name с изменениями. Поскольку ссылка на имя человека остается прежней, никаких изменений в Person или PersonAudit не требуется.

Если происходит «2», мы копируем исходную запись в PersonAudit и обновляем запись Person с изменениями. Поскольку часть имени не изменилась, никаких изменений в Name или NameAudit не требуется.

Если появляется «3», мы обновляем нашу базу данных в соответствии с двумя методами выше.

Если мы должны были внести 100 изменений как в части имени, так и в часть имени, одна проблема возникает, когда вы позже попытаетесь показать историю изменений. Все мои изменения показывают человека, имеющего последнюю версию имени. Что, очевидно, неправильно.

Чтобы исправить это, может показаться, что поле NameID в Person должно ссылаться на NameAudit (но только если в Name есть изменения).

И именно эта условная логика начинает усложнять вещи.

Мне было бы любопытно узнать, сталкивался ли кто-нибудь с подобными проблемами с их базой данных и какое решение было применено?

Ответы [ 2 ]

6 голосов
/ 26 мая 2009

Возможно, вам следует попробовать прочитать об обработке «временной базы данных». Вы можете взглянуть на две книги: Дарвен, Дейт и Лоренцо: « Временные данные и реляционная модель » и (в корне иной крайности) « Разработка ориентированных на время приложений баз данных в SQL » Ричард Т. Снодграсс, Morgan Kaufmann Publishers, Inc., Сан-Франциско, июль 1999 г., 504 + xxiii pages, ISBN 1-55860-436-7. Это распечатано, но доступно в формате PDF на его веб-сайте cs.arizona.edu . Вы также можете искать « Отношения Аллена » для интервалов - они могут быть вам полезны.


Я предполагаю, что тип DATE в вашей базе данных включает время (поэтому вы, вероятно, используете Oracle). Стандартным типом SQL, вероятно, будет TIMESTAMP с некоторым количеством дробных цифр для разрешения менее секунды. Если ваша СУБД не включает время с DATE, тогда вы столкнетесь с трудной проблемой, решая, как обрабатывать несколько изменений за один день.

То, что вам нужно показать, предположительно, - это история изменений в любой таблице с соответствующими значениями из другой таблицы, которые действовали на момент внесения изменений. Вы также должны решить, является ли то, что вы показываете, изображением до или после; по-видимому, снова, после изображения. Это означает, что у вас будет «упорядоченный» запрос (термин Снодграсса) с такими столбцами, как:

Start time        -- When this set of values became valid
End time          -- When this set of values became invalid
PersonID          -- Person.ID (or PersonAudit.ID) for Person data
NameID            -- Name.ID (or NameAudit.ID) for Name data
DOB               -- Date of Birth recorded while data was valid
Email             -- Email address recorded while data was valid
FirstName         -- FirstName recorded while data was valid
LastName          -- LastName recorded while data was valid
NickName          -- NickName recorded while data was valid

Я предполагаю, что как только Person.ID установлен, он не меняется; То же самое для Name.ID. Это означает, что они остаются действительными, пока записи сохраняются.

Одной из сложных частей в этом является установление правильного набора значений «время начала» и «время окончания», поскольку переходы могут происходить в любой таблице (или в обеих). На данный момент я даже не уверен, что у вас есть все необходимые данные. Когда вставляется новая запись, вы не фиксируете время, когда она становится действительной (в таблице XYZAudit при вставке новой записи ничего нет, не так ли?).


Можно сказать гораздо больше. Однако, прежде чем идти дальше, я бы хотел получить некоторые отзывы о некоторых поднятых проблемах.


Некоторые другие вопросы, которые могут помочь:


Поскольку этот ответ был впервые написан, была опубликована еще одна книга о другом наборе методов, называемых «Утвержденные версии» для обработки временных данных. Книга Тома Джонстона и Рэндалла Вайса « Управление временем в реляционных базах данных: как проектировать, обновлять и запрашивать временные данные ». Вы можете найти их компанию на AssertedVersioning.com . Осторожно: вокруг механизма могут быть проблемы с патентами.

Также был опубликован стандарт SQL 2011 (ISO / IEC 9075: 2011, в нескольких частях). Включает поддержку временных данных. Вы можете узнать больше об этой и других проблемах, связанных с временными данными, по адресу TemporalData.com , который является скорее информационным сайтом, а не сайтом с особым товарным топором.

0 голосов
/ 26 мая 2009

Сохраните таблицу изменений с автоинкрементом ID и внесите все изменения, чтобы обратиться к этой таблице.

Всегда помещайте исходную запись в таблицу аудита.

Чтобы построить историю, выберите все ваши изменения и покажите значение, наиболее близкое к изменению.

Как это:

`Change`

1
2
3
4
5
6

`NameAudit`

1 - created as John Smith
5 - changed to James Smith

`PersonAudit`

1 - created as born on `01.01.1980` in `Seattle, WA`
2 - changed DOB to '01.01.1980`
3 - changed DOB to '02.01.1980`
4 - changed DOB to '02.01.1980`
6 - changes POB to `Washington, DC`

Затем выберите:

SELECT  c.id,
        (
        SELECT   MAX(id)
        FROM     NameAudit na
        WHER     na.id <= c.id
        ) as nameVersion,
        (
        SELECT   MAX(id)
        FROM     PersonAudit pa
        WHER     pa.id <= c.id
        ) as personVersion,
        na.*,
        pa.*
FROM    change c
JOIN    NameAudit na
ON      na.id = nameVersion
JOIN    PersonAudit pa
ON      pa.id = nameVersion
WHERE   change_id BETWEEN 1 AND 6
...