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

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

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


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

 - 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-данные могут быть частью объекта.


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

Затем его можно разбить вместе с VIEW таблицы, который может как бы навязывать любые последующие версии отдельных данных столбцов в микс для создания последней версии, но без необходимости хранить ВСЕ данные для каждой небольшой ревизии.

+----+--------+--------+
| 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, но подумал, так как я здесь изобретал функциональность, почему бы не сходить с ума.

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

1 ответ

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

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

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

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

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

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

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

Другие вопросы по тегам