Сведения о вопросе

CPdeveloper

12:22, 29th August, 2020

Теги

architecture   time   rdbms   versions    

Дебаты по дизайну: каковы хорошие способы хранения и управления версионными объектами?

Просмотров: 493   Ответов: 5

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

Я нахожусь в середине разработки приложения, которое делает что-то вроде управления портфелем. Дизайн, который у меня есть до сих пор, - это

  • Проблема: проблема, которую необходимо решить
  • Решение: предлагаемое решение одной или нескольких проблем
  • Отношение: отношение между двумя проблемами, двумя решениями или проблемой и решением. Далее разбивается на:
    • Родитель-ребенок - своего рода категоризация / иерархия дерева
    • Перекрытие-степень, в которой два решения или две проблемы действительно решают одну и ту же концепцию
    • Адреса-степень, в которой проблема обращается к решению

Мой вопрос касается временной природы этих вещей. Проблемы возникают, а затем исчезают. Решения имеют ожидаемую дату разрешения, но она может быть изменена по мере их разработки. Степень взаимосвязи может меняться с течением времени по мере развития проблем и решений.

Итак, вопрос: каков наилучший дизайн для версирования этих вещей, чтобы я мог получить как текущую, так и историческую перспективу своего портфолио?

Позже: возможно, я должен сделать это более конкретным вопросом, хотя ответ @Eric Beard стоит того.

Я рассмотрел три проекта баз данных. Я буду достаточно каждого, чтобы показать свои недостатки. Мой вопрос: Что выбрать, или вы можете придумать что-то лучше?

1: проблемы (и отдельно, решения) являются самореферентными в управлении версиями.

table problems
  int id | string name | text description | datetime created_at | int previous_version_id

  foreign key previous_version_id -> problems.id

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

2: Создайте новый тип отношений: версия.

table problems
  int id | string name | text description | datetime created_at

Это просто перемещает отношения из таблиц проблем и решений в таблицу отношений. Та же проблема дублирования, но, возможно, немного "cleaner", так как у меня уже есть абстрактная концепция отношений.

3: Используйте более Субверсионную структуру; переместите все атрибуты проблемы и решения в отдельную таблицу и версируйте их.

table problems
  int id

table attributes
  int id | int thing_id | string thing_type | string name | string value | datetime created_at | int previous_version_id

  foreign key (thing_id, thing_type) -> problems.id or solutions.id
  foreign key previous_version_id -> attributes.id

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

еще позже: ответ на комментарии @Eric Beard о внешних ключах с несколькими таблицами:

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



  Сведения об ответе

darknet

06:06, 2nd August, 2020

Хм, похоже на этот сайт...

Что касается дизайна базы данных, система управления версиями, такая как SVN, где вы никогда не делаете никаких обновлений, просто вставляете (с номером версии), когда все меняется, может быть тем, что вам нужно. Это называется MVCC, управление многозначным параллелизмом. А wiki-еще один хороший пример этого.


  Сведения об ответе

park

20:14, 7th August, 2020

@Gaius

foreign key (thing_id, thing_type) -> problems.id or solutions.id

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

problem_id and solution_id 

будет работать намного лучше.

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


  Сведения об ответе

прога

16:25, 6th August, 2020

Как вы думаете об этом:

проблемы таблицы
int id / имя строки / текстовое описание / datetime created_at

таблица problems_revisions
пересмотр инт | инт код | наименование строки | текстовое описание | datetime created_at
идентификатор внешнего ключа - > problems.id

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

  1. эффективный доступ к текущей версии-выберите проблемы как обычно
  2. схема, которая интуитивно понятна и близка к реальности, которую вы хотите смоделировать
  3. соединения между таблицами в схеме сохраняют эффективность
  4. используя номер версии для каждой транзакции шины, вы можете выполнять управление версиями над записями таблицы, как SVN делает над файлами.


  Сведения об ответе

qwerty101

02:54, 12th August, 2020

Я полагаю, что есть

Вариант 4: гибрид

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

Если description и другие большие поля остаются в таблице вещей, это также не решает проблему дублирования пространства.

table things
  int id | int type | string name | text description | datetime created_at | other common fields...
  foreign key type -> thing_types.id

table custom_attributes
  int id | int thing_id | string name | string value
  foreign key thing_id -> things.id

  Сведения об ответе

ЯЯ__4

18:14, 13th August, 2020

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

У меня были бы таблицы для проблемы, решения и отношений, которые представляют текущую позицию. Там также будет таблица problem_history , solution_history и т. д. Это будут дочерние таблицы проблем, но также содержат дополнительные столбцы для VersionNumber и EffectiveDate . Ключ будет ( ProblemId, VersionNumber).

Когда вы обновляете проблему, вы записываете старые значения в таблицу problem_history . Поэтому запросы на момент времени возможны, поскольку вы можете выбрать запись problem_history , которая действительна as-at на определенную дату.

Там, где я делал это раньше, я также создал представление UNION problem и problem_history , поскольку это иногда полезно в различных запросах.

Вариант 1 затрудняет запрос текущей ситуации, так как все ваши исторические данные смешиваются с текущими данными.

Вариант 3 будет плохим для производительности запросов и неприятным для кода, поскольку вы будете получать доступ к большому количеству строк для того, что должно быть просто простым запросом.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться