Проблема моделирования реляционных объектов - PullRequest
0 голосов
/ 05 декабря 2008

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

У меня следующая проблема:

У меня есть «вопросы», которые должны быть в определенном «состоянии», и все изменения состояния должны проверяться.

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

Вот изображение с обеими диаграммами.

EDIT:

Вариант A: таблица «questions» не должна содержать state_id, а Question_State не должна содержать поле «id». Извините за ошибки.

EDIT2

Спасибо за все примеры из реальной жизни и понимание, но это была академическая проблема, не связанная с реальным миром:).

Диаграммы http://i38.tinypic.com/2v27epl.png

Ответы [ 6 ]

5 голосов
/ 05 декабря 2008

Я думаю, что суть того, что вы спрашиваете: должно ли состояние вопроса основываться на промежуточной таблице между вопросами и состоянием, в которой есть компонент времени (A), или таблица должна быть более статичной, но с журнал истории на стороне (B).

(Примечание: если вы хотите сделать чистую версию (A), то Boofus прав, вы, вероятно, не поместили бы и state_id в таблицу вопросов, так как это избыточно; но это определенно было бы неудобно, потому что это будет делать простые запросы, чтобы получить вопросы в определенном состоянии гораздо сложнее. Итак, у вас есть гибридная версия здесь.)

В общем, если требование хранить историческую информацию о состоянии действительно только для целей аудита - то есть, если оно не будет регулярно запрашиваться самим приложением - вам, вероятно, лучше использовать вариант B, потому что это немного проще (на самом деле есть только одна таблица «Вопросы», со справочной таблицей для состояний и таблицей «Журнал» для предыдущих состояний). Я думаю, что это показывает ваши намерения немного лучше.

Однако, если семантика приложения является более сложной (например, если у вас есть запросы типа «показать все вопросы, которые были в состоянии X в течение последних 24 часов ...»), то такой подход, как (A), может привести к больше смысла. По сути, это превращает состояние вопроса в факт, зависящий от времени. Если вы сделаете это, просто знайте, что это усложняет ситуацию - либо все ваши запросы сложнее и требуют времени, либо вам нужно беспокоиться о том, чтобы синхронизировать state_id в вопросах с самым последним состоянием в таблице вопросов. Если вы идете по этому пути, возможно, назовите его «current_state» или что-то в вопросах, так что ясно, что это своего рода производная информация.

1 голос
/ 06 декабря 2008

Возможно, вы захотите прочесать в Интернете тему «временные базы данных». По сути, хранение истории изменений любой переменной порождает одни и те же проблемы, независимо от того, фиксирует ли переменная состояние вопроса, вес человека или что-то еще.

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

В-третьих, мне больше нравится вариант B, но он действительно зависит от того, что вы собираетесь делать с данными.

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

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

0 голосов
/ 08 декабря 2008

Я не понял, как и # Boofus, интерес к наличию поля state_id в таблице вопросов.

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

alt text

Для ситуаций с несколькими состояниями идея состоит в том, чтобы проверить, имеет ли значение end_date значение null (другой идеей было бы иметь логическое поле isActiveState в таблице). Не стоит недооценивать интерес к этой конфигурации с несколькими состояниями. Пример:

Вопрос может быть

  • закрыто и решено

или

  • закрыто и не решено.

Это может соответствовать двум различным состояниям:

  • Состояние "Закрыто и решено"

или

  • Состояние "Закрыто и не решено"

Но я думаю, что лучшим решением было бы иметь

  • Состояние «открыто / закрыто»

и

  • Состояние "Разрешено / Неразрешено"

И чтобы вопрос имел несколько состояний

0 голосов
/ 05 декабря 2008

Вы говорите «проверено», что означает, что вы просто хотите сохранить историческую информацию для целей отчетности. В этом случае я бы предположил, что диаграмма B более понятна, хотя вам, вероятно, следует отметить отношения «один ко многим» между Вопросами и Историческим, а также Государственным и Историческим.

Что касается практичности, если бы обстоятельства были такими, как указано выше, я сам включил бы функцию исторической вставки в триггер вставки / обновления в вопросах, и если объем таблицы вопросов и / или число изменений состояния будет было бы важно, чтобы я поместил Историческую таблицу в другую базу данных. Это просто облегчает управление базой данных позже. Обычно я настороженно отношусь к триггерам, так как чрезмерное использование может привести к сложным для обслуживания базам данных (так как не сразу понятно, что происходит), но это очевидный случай, когда они хорошо подходят и являются лучшим выбором для использования логика приложения.

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

0 голосов
/ 05 декабря 2008

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

Затем укажите столбец Состояние в таблице вопросов и таблицу аудита.

0 голосов
/ 05 декабря 2008

Как только вы нарисуете все отношения, они будут одинаковыми.

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

Мне кажется, что если вы хотите узнать текущее состояние вопроса, вы делаете

ВЫБРАТЬ State_ID ИЗ Исторического ГДЕ Question_id =? ЗАКАЗАТЬ ПО ДАТЕ DESC LIMIT 1

(или любой другой метод, который использует ваш SQL-код, чтобы ограничить его только одной строкой)

...