Может ли кто-нибудь предложить метод управления версиями данных 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.