Может ли кто-нибудь предложить метод управления версиями данных ATTRIBUTE (а не OBJECT) в БД

Возьмем MySQL в качестве примера БД для выполнения этого (хотя на данном этапе я не ограничен реляционными вариантами) и синтаксис стиля Java для взаимодействия модели/БД.

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


Простым примером может быть

 - Food (Table)
     - id (INT)
     - name (VARCHAR(255))
     - weight (DECIMAL) 

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

Food banana = new Food("Banana",0.3);

давая нам

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.3    |
+----+--------+--------+

если мы затем хотим обновить вес, мы могли бы использовать

banana.weight = 0.4;
banana.save();

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.4    |
+----+--------+--------+

Очевидно, что это приведет к перезаписи данных.

Я мог бы добавить в эту таблицу столбец ревизий, который можно было бы увеличивать по мере сохранения элементов, и установить составной ключ, объединяющий идентификатор/версию, но это все равно означало бы сохранение ВСЕХ атрибутов этого объекта для каждой отдельной ревизии.

- Food (Table)
      - id (INT)
      - name (VARCHAR(255))
      - weight (DECIMAL) 
      - revision (INT)

+----+--------+--------+----------+
| id |  name  | weight | revision |
+----+--------+--------+----------+
|  1 | Banana | 0.3    |        1 |
|  1 | Banana | 0.4    |        2 |
+----+--------+--------+----------+

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


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

Затем это можно было бы разбить вместе с ПРОСМОТРОМ таблицы, который мог бы как бы наложить любые более поздние версии данных отдельных столбцов в микс для создания последней версии, но без необходимости хранить ВСЕ данные для каждой небольшой версии.

+----+--------+--------+
| id |  name  | weight |
+----+--------+--------+
|  1 | Banana | 0.3    |
+----+--------+--------+

+-----+------------+-------------+-----------+-----------+----------+
| ID  | TABLE_NAME | COLUMN_NAME | OBJECT_ID | BLOB_DATA | REVISION |
+-----+------------+-------------+-----------+-----------+----------+
| 456 | Food       | weight      |         1 | 0.4       |        2 |
+-----+------------+-------------+-----------+-----------+----------+

Не уверен, насколько успешным может быть сохранение любых данных в виде большого двоичного объекта для последующего CAST обратно в исходный DTYPE, но подумал, что, поскольку я изобретал здесь функциональность, почему бы не сойти с ума.

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


person BizNuge    schedule 22.08.2015    source источник


Ответы (1)


Таблица в 6NF имеет один CK (кандидатный ключ) (в SQL a PK) и не более одного другого столбца. По сути, 6NF позволяет записывать время/версию и значение каждого столбца таблицы до 6NF без аномалий. Вы декомпозируете таблицу, удаляя столбец, не являющийся простым, и добавляя таблицу с ним, а также столбцы старого CK. Для временных/версионных приложений вы дополнительно добавляете столбец времени/версии, а новый CK – это старый плюс его.

Добавление столбца времени/любого интервала (в столбцах времени начала и окончания SQL) вместо времени в CK позволяет выполнять своего рода сжатие данных путем записи самых длинных непрерывных отрезков времени или другого измерения, в котором столбец имел одно и то же значение. Один запрашивает исходный CK плюс время, значение которого вы хотите. Вам это не нужно для ваших целей, но начальный процесс нормализации до 6NF и добавление столбца времени/независимо должны быть объяснены во временных учебниках.

Прочтите о временных базах данных (которые работают как с "достоверными" данными, такими как время и временные интервалы, также "транзакционные" времена/версии обновлений базы данных) и 6NF и его роль в них. (Snodgrass/TSQL2 плох, Date/Darwen/Lorentzos хорош, а SQL проблематичен.)

Ваша последняя предлагаемая таблица является примером EAV. Обычно это антипаттерн. Он кодирует базу данных в одну или несколько таблиц, которые фактически являются метаданными. Но так как СУБД не знает, что вы теряете большую часть своей функциональности. EAV не требуется, если DDL достаточно для управления таблицами с нужными вам столбцами. Просто объявите соответствующие таблицы в каждой базе данных. Это действительно одна база данных, поскольку вы ожидаете, что транзакции затрагивают обе. Из этой ссылки:

Вы используете анти-шаблон EAV СУБД. Вы (пытаетесь) встроить часть СУБД в свою программу + базу данных. СУБД уже существует для управления данными и метаданными. Используй это.

Не иметь класса/таблицы метаданных. Просто атрибуты фильмов должны быть полями/столбцами фильмов.

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

person philipxy    schedule 23.08.2015
comment
приносим свои извинения за то, что не приняли этот ответ 5 лет назад. Хороший ответ и счастливого 2020 года. - person BizNuge; 06.01.2020