База данных - Версии данных

Я прочитал несколько вопросов о SO (например, этот) в отношении версий ваших данных в базе данных.

Мне понравились некоторые из упомянутых предложений. Я долгое время хотел (необходимости) пересмотреть многие мои таблицы, но так и не добрался до него. Будучи программистом с простой работой с базой данных под моим поясом, мне было интересно, как это вообще можно было бы сделать.

Я не запрашиваю фактическое решение в синтаксисе SQL. В конце концов я смогу понять это для себя (или опубликую СО, когда придет время). Я просто прошу людей прокомментировать, как они это сделают, и любые потенциальные проблемы с производительностью, которые могут возникнуть, если я буду "пересматривать" сотни миллионов записей. Или любые другие предложения, если они основаны на приведенном ниже примере.

Учитывая простой пример:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL

Audit
------------------------------------------------
ID                UINT NOT NULL,
UserID            UINT NOT NULL,               -- Who
TableName         VARCHAR(50) NOT NULL,        -- What
OldRecID          UINT NOT NULL,               -- Where
NewRecID          UINT NOT NULL,
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

Я не уверен, как связать таблицу Audit с любыми другими таблицами (например, Person), если TableName является строкой?

Кроме того, предполагая, что у меня есть три GUI для заполнения:

  • Полная запись для идентификатора конкретного человека
  • В виде таблицы перечислены все лица (по id)
  • Вид, показывающий каждого человека с информацией о его пересмотре ниже каждой записи (# ревизий на человека, даты пересмотров, комментарии к пересмотру и т.д.), упорядоченные по последним версиям.

Чтобы выполнить 1 и 2, было бы лучше запросить таблицу Person или таблицу аудита?

Чтобы выполнить 3, может ли так называемый эксперт базы данных просто получить все записи и передать их на программное обеспечение для обработки или группу по идентификатору PersonID и Affected date? Обычно ли это обрабатывается одним запросом или многими?

Ответ 1

Я выполнял различные схемы аудита на протяжении многих лет, и сейчас я собираюсь реализовать что-то вроде этого:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL


Person_History
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL
AuditID           UINT NOT NULL


Audit
------------------------------------------------
ID                UINT NOT NULL,
UserID            UINT NOT NULL,               -- Who
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

Текущие записи всегда находятся в таблице Person. Если есть изменение, создается запись аудита и старая запись копируется в таблицу Person_History (обратите внимание, что идентификатор не изменяется и может быть несколько версий).

Идентификатор аудита находится в таблицах * _History, поэтому вы можете связать несколько записей с одной записью аудита, если хотите.

EDIT:
Если у вас нет отдельной таблицы истории для каждой базовой таблицы и вы хотите использовать ту же таблицу для хранения старых и "удаленных" записей, вы должны пометить записи флагом состояния. Проблема с тем, что это настоящая боль при запросе текущих записей - поверьте мне, я это сделал.

Ответ 2

Как насчет того, чтобы вы создали таблицу в обычном режиме, на каждой записи (и ModifiedBy, если хотите), есть столбец ModifiedDate, а также весь доступ к данным через материализованное представление, которое группирует данные по идентификатору, а затем делает HAVING ModifiedDate = MAX (ModifiedDate)?

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

Я всегда обнаружил, что различные таблицы с одинаковыми столбцами являются сложными и подверженными ошибкам.

Ответ 3

Следуя сообщению DJ в истории таблицы для каждой базовой таблицы и комментариях Карла о возможных проблемах с производительностью, я немного поработал над SQL-исследованием, чтобы выяснить самый быстрый способ переноса записи из одной таблицы в другой.

Я просто хотел документировать, что я нашел:

Я подумал, что мне нужно будет выполнить выборку SQL для загрузки записи из базовой таблицы, а затем с помощью SQL push, чтобы поместить запись в таблицу истории, а затем обновить базовую таблицу, чтобы вставить измененные данные, Всего 3 транзакции.

Но, к моему удивлению, я понял, что вы можете сделать первые две транзакции, используя один оператор SQL, используя синтаксис SELECT INTO. Я уверен, что производительность будет в сто раз быстрее делать это.

Тогда это оставит нас просто ОБНОВИТЬ запись с новыми данными в базовой таблице.

Я все еще не нашел один оператор SQL для выполнения всех трех транзакций одновременно (я сомневаюсь, что это произойдет).

Ответ 4

Мне нравится ваша аудиторская таблица, ее хороший старт. У вас есть проблема с кардинальностью в вашей таблице аудита, поэтому я бы разоблачил ее как две таблицы:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL,
AuditID           UINT NOT NULL 

Audit
------------------------------------------------
ID                UINT NOT NULL,
TableName         VARCHAR(50) NOT NULL,        -- What
TableKey          UINT NOT NULL,
CreateDate        DATETIME NOT NULL  DEFAULT(NOW),
CreateUserID      UINT NOT NULL,
ChangeDate        DATETIME NOT NULL  DEFAULT(NOW),
ChangeUserID      UINT NOT NULL

Audit_Item
------------------------------------------------
ID                UINT NOT NULL,
AuditID           UINT NOT NULL,               -- Which audit record
UserID            UINT NOT NULL,               -- Who
OldRecID          UINT NOT NULL,               -- Where
NewRecID          UINT NOT NULL,
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

В предложенном исходном макете имеется одна запись аудита, которая указывает на (я предполагаю) две записи Person. Задачами этого проекта являются:

  • Какие записи в вашей таблице текущие "реальные" записи?
  • Как вы представляете всю историю изменений в записи Person? Если вы указываете на две записи в таблицу Person, затем см. пункт № 1: какой из них является текущей записью?
  • Сбрасываются поля Create *, Change * из коллекции Audit_Item записей. Они существуют только для Простота доступа.
  • Ключ AuditID в таблице Person позволяет вам указывать вернуться к таблице аудита и перейти к история отдельного Лица без необходимости запрашивать аудит таблица с предложением WHERE TableName='Person'