Как создать базу данных с историей изменений?

Я являюсь частью команды, создающей новую систему управления контентом для нашего публичного сайта. Я пытаюсь найти самый простой и лучший способ встроить механизм контроля версий. Объектная модель довольно проста. У нас есть абстрактный класс "BaseArticle", который включает свойства для независимых от версии/метаданных, таких как "Заголовок" и "CreatedBy". Ряд классов наследуется от этого, например, "DocumentArticle", который имеет свойство "URL", который будет путь к файлу. "WebArticle" также наследует от "BaseArticle" и включает в себя свойство "ДалееInfo" и коллекцию объектов "Tabs", которые включают в себя "Body", который будет содержать HTML-код для отображения (объекты Tab не являются производными от чего-либо). "NewsArticle" и "JobArticle" наследуют от "WebArticle". У нас есть другие производные классы, но они предоставляют достаточный пример.

Мы предлагаем два подхода к сохранению Revision Control. Я называю это "подход 1" и "подход 2". Я использовал SQL Server для создания базовой схемы каждого из них: Database Diagram of Approach 1Database Diagram of Approach 2

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

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

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

Мы используем SQL Server 2005, хотя я думаю, что этот вопрос не зависит от вида базы данных. Я провел несколько обширных поисков в интернете и нашел ссылки на оба подхода. Но я не нашел ничего, что сравнило бы эти два и показало бы одно или другое, чтобы быть лучше. Я думаю, что со всеми книгами по базам данных в мире, этот выбор подходов должен был возникнуть раньше.

У меня вопрос: какой из этих подходов является лучшим и почему?

Ответы

Ответ 1

Я бы сказал, что Подход 2. Это проще, кажется, намного проще реализовать, и он обеспечивает ту же функциональность, что и подход 1.

Что еще я могу добавить?

Ответ 2

Ни.

CMS сложна, и это может быть настоящей болью - болью в работе с заблокированными файлами базы данных, когда кто-то отключает интернет. Поскольку вы используете MSSQL, просто можете загрузить и использовать подпадающие под GPL программы Joomla !, mediaWiki или Magnolia и избавить свою компанию от головной боли в будущем, когда вы решите уйти.

Тем не менее, что-то похожее в Approch2 - это то, как я обычно вижу реализованные системы CMS.

Ответ 3

В общем, самое большое преимущество для таблиц истории/аудита - это производительность:

  • любые живые/активные данные могут быть запрошены из намного меньшей основной таблицы

  • Любые запросы "только в режиме реального времени" не обязательно должны содержать флаг "активный/последний" (или, не дай бог, сделать коррелированный подзапрос на временной метке для определения последней строки), что упрощает код как для разработчиков, так и для оптимизатора движка БД.

Однако для небольших CMS с сотнями или тысячами строк (а не миллионами строк) прирост производительности будет довольно небольшим.

Таким образом, для небольших CMS подход 3 будет лучше, поскольку он проще: меньше кода, меньше движущихся частей.

Подход 3 почти такой же, как и подход 2, за исключением того, что каждая таблица, для которой требуется история/управление версиями, имеет явный столбец, содержащий истинный/ложный "активный" (также известный как "последний") - флаговый столбец.

Ваши пользователи несут ответственность за правильное управление этим столбцом при вставке новой действующей версии (или удалении текущей активной версии) строки.

Все ваши "живые" запросы на выборку за пределами UPSERT затем будут тривиально изменить, добавив " AND mytable.live = 1 " к любому запросу.