Довольно распространенным требованием в приложениях баз данных является отслеживание изменений одной или нескольких конкретных сущностей в базе данных. Я слышал, что это называется управлением версиями строк, таблицей журнала или таблицей истории (я уверен, что для нее есть другие названия). Есть несколько способов подойти к этому в РСУБД - вы можете записывать все изменения из всех исходных таблиц в одну таблицу (больше журнала) или иметь отдельную таблицу истории для каждой исходной таблицы. У вас также есть возможность управлять регистрацией в коде приложения или с помощью триггеров базы данных.
Я пытаюсь понять, как будет выглядеть решение той же проблемы в базе данных NoSQL / document (в частности, MongoDB) и как это будет решаться единообразно. Будет ли это так же просто, как создать номера версий для документов и никогда не перезаписывать их? Создание отдельных коллекций для "реальных" и "зарегистрированных" документов? Как это повлияет на запросы и производительность?
В любом случае, это обычный сценарий с базами данных NoSQL, и если да, то есть ли общее решение?
Ответы:
Хороший вопрос, я тоже этим занимался.
Создавать новую версию при каждом изменении
Я наткнулся на модуль управления версиями драйвера Mongoid для Ruby. Я сам не использовал его, но, насколько мне удалось найти , он добавляет номер версии к каждому документу. Более старые версии встроены в сам документ. Главный недостаток заключается в том, что весь документ дублируется при каждом изменении , что приводит к сохранению большого количества дублированного контента, когда вы имеете дело с большими документами. Этот подход хорош, когда вы имеете дело с документами небольшого размера и / или не обновляете документы очень часто.
Сохранять изменения только в новой версии
Другой подход - сохранить в новой версии только измененные поля . Затем вы можете «сгладить» свою историю, чтобы восстановить любую версию документа. Однако это довольно сложно, поскольку вам нужно отслеживать изменения в вашей модели и сохранять обновления и удаления таким образом, чтобы ваше приложение могло восстановить актуальный документ. Это может быть сложно, поскольку вы имеете дело со структурированными документами, а не с плоскими таблицами SQL.
Сохранять изменения в документе
Каждое поле также может иметь индивидуальную историю. Таким образом, восстановить документы до заданной версии намного проще. В вашем приложении вам не нужно явно отслеживать изменения, а просто создавать новую версию свойства при изменении его значения. Документ может выглядеть примерно так:
Однако отмечать часть документа как удаленную в версии все еще несколько неудобно. Вы можете ввести
state
поле для частей, которые можно удалить / восстановить из вашего приложения:С помощью каждого из этих подходов вы можете хранить актуальную и упорядоченную версию в одной коллекции, а данные истории - в отдельной коллекции. Это должно сократить время запроса, если вас интересует только последняя версия документа. Но когда вам нужна как последняя версия, так и исторические данные, вам нужно будет выполнить два запроса, а не один. Таким образом, выбор использования одной коллекции или двух отдельных коллекций должен зависеть от того, как часто вашему приложению нужны исторические версии .
По большей части этот ответ - всего лишь свалка моих мыслей, я еще ничего из этого не пробовал. Оглядываясь назад, можно сказать, что первый вариант, вероятно, является самым простым и лучшим решением, если только накладные расходы на дублирование данных не очень значительны для вашего приложения. Второй вариант довольно сложен и, вероятно, не стоит усилий. Третий вариант в основном является оптимизацией второго варианта и должен быть проще в реализации, но, вероятно, не стоит усилий по реализации, если только вы действительно не можете выбрать вариант один.
Жду отзывов по этому поводу и других решений проблемы :)
источник
Мы частично реализовали это на нашем сайте и используем «Сохранить изменения в отдельном документе» (и в отдельной базе данных). Мы написали специальную функцию для возврата изменений и сохраняем ее. Это не так сложно и может позволить автоматическое восстановление.
источник
Почему бы не сделать вариант « Сохранить» в документе ?
Вместо хранения версий каждой пары ключей, текущие пары ключей в документе всегда представляют самое последнее состояние, а «журнал» изменений сохраняется в массиве истории. Только те ключи, которые изменились с момента создания, будут занесены в журнал.
источник
Можно иметь текущую базу данных NoSQL и историческую базу данных NoSQL. Каждый день будет проводиться ночная ETL. Этот ETL будет записывать каждое значение с меткой времени, поэтому вместо значений всегда будут кортежи (версионные поля). Он будет записывать новое значение только в том случае, если в текущее значение было внесено изменение, что позволяет сэкономить место в процессе. Например, этот исторический json-файл базы данных NoSQL может выглядеть так:
источник
Для пользователей Python (конечно, python 3+ и выше) существует HistoricalCollection, который является расширением объекта Collection от pymongo.
Пример из документов:
Полное раскрытие, я являюсь автором пакета. :)
источник