Проблема проектирования базы данных SQL
Я создаю базу данных для мониторинга состояния функциональности приложений. Логика следующая:
Каждое приложение имеет свой собственный список функций, которые я отслеживаю. Каждый функционал принадлежит только одному приложению. Есть таблица Функциональности, у которой есть внешний ключ к Приложению
Каждое приложение выполняется на одной или нескольких машинах. На каждой машине может работать одно или несколько приложений. Это соединение MTM, поэтому есть таблица соединения ApplicationInstance Applications с машинами.
Фактический мониторинг касается запросов ApplicationInstance. Если возникает проблема, информация о ней поступает в таблицу AppInstanceError, которая содержит внешний ключ для ApplicationInstance. Если запрос выполнен успешно, мы получаем список статусов каждой функции. Итак, у нас есть таблица FunctionalityStatus с внешними ключами для ApplicationInstance & Functionality.
Я думаю, что это плохой дизайн - почему у нас есть несколько ссылок на приложение? Что гарантирует, что оба будут указывать на одно и то же приложение? Или есть ли способ это обеспечить?
Таким образом, мое предложение исправить это соединить FunctionalityStatus с внешними ключами для Machines & Functionality. Но в этом случае они определяют ApplicationInstance, так какова гарантия наличия ApplicationInstance для каждой пары? Разве они не должны быть связаны как-то? В реальном мире связь существует и очевидна, так что нормально, если ее нет в базе данных?
Существует ли "более совершенный способ" решения этой проблемы или обеспечения невидимых соединений при проектировании данных?
Чтобы было понятнее, я подготовил дизайн БД, который у меня сейчас есть: http://img6.imageshack.us/img6/7479/dbexample.png
Единственное, чего не хватает, так это соединения между FunctionalityStatus и Machine. Я вижу два способа сделать такое соединение:
- Добавьте внешний ключ в ApplicationInstance - тогда я сомневаюсь:
- Как убедиться, что ApplicationId из Functionality такой же, как и из ApplicationInstance?
- Разве это дублирование данных действительно необходимо?
- Добавить внешний ключ к машине - и сомневается:
- Будет ли для каждой записи FunctionalityStatus более точная запись ApplicationInstance?
- Если существует очевидная связь между ApplicationInstance и FunctionalityStatus (упомянутое в первом сомнении), почему мы не можем увидеть его в базе данных?
- Опять избыточность данных, потому что все записи ApplicationInstance (или должны быть) видны в таблице FunctionalityStatus
Или, может быть, весь дизайн облажался, и я должен выяснить что-то совершенно другое?
3 ответа
Ваш дизайн мне подходит. Я бы пошел на вариант 1, добавив внешний ключ от FunctionalStatus
в ApplicationInstance
,
Если вы хотите убедиться, что FunctionalStatus
а также ApplicationStatus
обратитесь к тому же приложению, вы можете добавить новый столбец FunctionalStatus.ApplicationId
и сделать внешний ключ из FunctionalStatus
в ApplicationStatus
включают ApplicationId
, Аналогично для внешнего ключа от FunctionalStatus
в Functionality
,
Другими словами, что-то вроде
CREATE TABLE application
( application_id INT PRIMARY KEY
/* Other columns omitted */
);
CREATE TABLE application_instance
( application_instance_id INT PRIMARY KEY
, application_id INT REFERENCES application(application_id)
, machine_id INT REFERENCES machine(machine_id)
/* Other columns omitted */
);
CREATE TABLE functionality
( functionality_id INT PRIMARY KEY
, application_id INT REFERENCES application(application_id)
/* Other columns omitted */
);
CREATE TABLE functionality_status
( functionality_status_id INT PRIMARY KEY
, application_id INT REFERENCES application(application_id)
, functionality_id INT /* Part of composite foreign key, see below */
, application_instance_id INT /* Part of composite foreign key, see below */
/* Other columns omitted */
FOREIGN KEY (functionality_id, application_id)
REFERENCES functionality(functionality_id, application_id)
FOREIGN KEY (application_instance_id, application_id)
REFERENCES application_instance(application_instance_id, application_id)
);
Самая большая проблема, с которой вы можете столкнуться, заключается в том, что всегда можно иметь одинаковые идентификаторы экземпляров для двух разных экземпляров одного и того же приложения на одном компьютере. Не может быть в одно и то же время, идентификаторы экземпляров многократно используются, и есть небольшая вероятность того, что ваше приложение снова получит тот же.
Когда я делаю такие вещи, я назначаю каждому приложению идентификатор GUID при запуске, что делает невозможным использование двух приложений с одинаковым идентификатором GUID, и затем я использую этот идентификатор GUID для отношений. Вам даже не нужно иметь информацию о машине во взаимосвязи, поскольку каждая машина никогда не создаст такой же GUID, как любая другая машина.
После ответа я понял, что действительно не ответил на ваш настоящий вопрос. Если вы хотите узнать, работает ли определенная функция определенным образом, лучше всего связать ее с машиной и приложением, где эта функция работает не так, как вам нужно, или у вас возникли проблемы с поиском, какая из них работает правильно, а какая один не прав.
Наличие трех таблиц, одной для машин, одной для приложений и одной для функциональности, было бы лучшим дизайном базы данных. В зависимости от того, что вы делаете, для программного обеспечения может быть проще и быстрее дублировать всю информацию о приложении и машине для каждого набора функций, с которыми вы работаете, особенно если информация о машине и приложении в любом случае является лишь одним полем. Вы действительно не хотите замедлять функционирование регистрации этой информации, если можете помочь, поэтому вы хотите, чтобы это было сделано быстро.
Если бы это был я, вот как бы я это сделал:
- Создайте 5 таблиц: Машина, Приложение, Функциональность, ApplicationPool и Журнал.
- Поместите столбец FK в Функциональность, то есть идентификатор Приложения, для которого существует Функциональность.
- ApplicationPool будет иметь столбец идентификатора компьютера, столбец идентификатора приложения, первичный ключ, который является либо GUID, либо идентифицированным идентификатором, идентификатор ApplicationInstance, который будет вашим ApplicationName + PK. Если вы можете это использовать, я бы назвал ваши приложения вашими машинами.
- Наконец, я бы создал таблицу Log и дал бы столбец FK, который ссылается на PK ApplicationPool. Затем каждый раз, когда вы регистрируете что-то, вы можете добавить это в таблицу Log, и вся ваша информация о приложении будет храниться отдельно.
Если это не близко, дайте мне знать, потому что я мог неправильно понять, что вы ищете.