По крайней мере в одном приложении мне нужно хранить старые версии записей в реляционной базе данных. Когда что-то нужно обновить, вместо этого будет добавлена новая копия, а старая строка будет отмечена как неактивная. Когда что-то нужно удалить, оно должно быть помечено как неактивное или удаленное.Как эффективно записывать версии в базу данных SQL
Существует простой пример: новые версии записи могут быть добавлены только в текущее время, заменяя по одной строке каждый. Это можно использовать для архивирования предыдущих записей при сохранении новых данных. Для этого, я хотел бы добавить следующие столбцы каждой таблицы:
VersionTime datetime -- Time when this versions becomes effective
IsCurrent bool -- Indicates whether this version is the most current (and not deleted)
Это хорошо, если вам нужно только знать, что самая последняя версия записи есть, и только перечислить предыдущие версии одной записи отдельно , Запросы по времени еще более болезненны, чем со вторым вариантом.
Более общий вариант заключается в следующем: Версии записей могут быть добавлены в любое время для любого заданного диапазона времени действия. Поэтому я могу заявить, что некоторые настройки объекта действительны до конца 2013 года, а другая версия действует в 2014 году, а другая версия будет действовать с 2015 года. Это можно использовать как для архивирования старых данных (как указано выше), так и для планирования вперед для использования разных данных в будущем (и для сохранения этой информации в виде архива). Для этого, я хотел бы добавить следующие столбцы каждой таблицы:
ValidFrom datetime -- Time when this version becomes valid (inclusive)
ValidTo datetime -- Time when this version becomes invalid (exclusive)
Второй подход в основном представляют собой первый, как хорошо, но это труднее знать, какая версия является самой последней - потому что вы можете также добавить версии для будущего. Кроме того, конструкция ValidFrom/ValidTo может объявлять перекрывающиеся диапазоны, и по определению в этом случае применяется строка с самым высоким ValidFrom.
Теперь мне интересно, как реализовать эффективное решение для управления и запроса таких данных. Обычно вы можете просто писать любые SQL-запросы с любыми типами WHERE, GROUP BY и JOIN, чтобы получить нужные вам записи. Но при применении версий вы должны рассмотреть правильную версию каждой записи. Поэтому вместо того, чтобы присоединяться к каждой версии записи из другой таблицы, необходимо добавить соответствующее условие, чтобы выбрать только версию, действительную в данный момент.
Пример:
SELECT a, b, c
FROM t1
Должно быть изменено на:
SELECT a, b, c
FROM t1
WHERE t1.ValidFrom <= :time AND t1.ValidTo > :time
ORDER BY t1.ValidFrom
LIMIT 1
Сложнее с таблицей присоединения:
SELECT a, b, c
FROM t1
LEFT JOIN t2 ON (t2.a = t1.a)
Должно быть изменено на:
SELECT a, b, c
FROM t1
LEFT JOIN t2 ON (t2.a = t1.a)
WHERE t1.ValidFrom <= :time AND t1.ValidTo > :time
AND t2.ValidFrom <= :time AND t2.ValidTo > :time
Это все еще не относится к выбору правильной версии перекрывающихся временных интервалов. Я мог бы добавить некоторый метод очистки, который выравнивает перекрывающиеся диапазоны времени версии, но я не знаю, насколько это было бы эффективно.
Я хочу создать класс (в C# в моем случае), который предоставляет методы для чтения и записи таких версий. Запись довольно проста, потому что запросы просты и легко контролируются транзакциями. но для запросов потребуется создание API, который принимает каждый фрагмент SQL SELECT-запроса и интеллектуально строит SQL-запрос для его выполнения. Метод thie query должен принимать только один дополнительный параметр, определяющий время для извлечения данных. В зависимости от диапазона действительности каждого объекта будут выбраны разные версии каждого из них.
Это, по сути, мои неполные мысли о данных версий и предоставление API для управления им. Вы уже сделали такое и хотели бы рассказать мне, что вы думаете об этом? У вас есть еще одна идея, которая хорошо работала? Можете ли вы предложить мне какие-либо советы о том, как реализовать этот API? Хотя я теоретически знаю, как это сделать, я думаю, что это большая работа, и я не могу оценить, насколько она будет работать.
Я не могу притворяться, что полностью понимаю ваш вопрос ... почему у вас нет таблицы аудита для каждой таблицы, которая заполняется записью с отметкой даты каждый раз, когда происходит обновление, вставка или удаление - и получают ваши данные оттуда? Наверное, мне что-то не хватает. –
Насколько я понимаю вас правильно: вы имеете в виду дублирование таблицы и сохранение самых недавно записанных данных в одной и всех предыдущих версиях (с датой) в другой таблице? Это будет охватывать только первый, более простой сценарий, а не второй. Кроме того, он ничего не говорит о выполнении запроса «точно в срок». – ygoe