Дизайн базы данных для мониторинга состояния функциональных возможностей приложений

Я создаю базу данных для мониторинга состояния функциональных возможностей приложений. Логика следующая:

Каждое приложение имеет свой собственный список функций, которые я отслеживаю. Каждая функциональность принадлежит только одному приложению. Существует таблица функций с внешним ключом для приложения.

Каждое приложение работает на одной или нескольких машинах. Каждая машина может запускать одно или несколько приложений. Это соединение MTM, поэтому существует соединение таблицы ApplicationInstance Applications with Machines.

Фактический мониторинг заключается в запросе ApplicationInstance. Если есть проблема, информация о ней попадает в таблицу AppInstanceError, которая содержит внешний ключ к ApplicationInstance. Если запрос выполнен успешно, мы получаем список статусов каждой функциональности. Итак, у нас есть таблица FunctionalityStatus с внешними ключами ApplicationInstance и Functionality.

Я думаю, что это плохой дизайн - почему у нас есть несколько ссылок на приложение? Какие гарантии, что оба будут указывать на одно и то же приложение? Или есть способ это обеспечить?

Поэтому мое предложение по исправлению состоит в том, чтобы связать FunctionalityStatus с внешними ключами с Machines & Functionality. Но в этом случае они определяют ApplicationInstance, так какова гарантия наличия ApplicationInstance для каждой пары? Разве они не должны быть как-то связаны? В реальном мире связь существует и очевидна, поэтому можно ли не иметь ее в базе данных?

Есть ли «правильный способ» решения этой проблемы или обеспечения связи, невидимой из дизайна данных?

Чтобы было понятнее, я подготовил дизайн БД, который у меня сейчас есть: Дизайн БД

Единственное, чего не хватает, так это подключения от FunctionalityStatus к Machine. Я вижу два пути создания такой связи:

  1. Add foreign key to ApplicationInstance - then my doubts are:
    • How to make sure that ApplicationId from Functionality is the same that one from ApplicationInstance?
    • Действительно ли необходимо это дублирование данных?
  2. Add foreign key to Machine - and doubts:
    • Will there be a propper ApplicationInstance record for every FunctionalityStatus record?
    • Если существует очевидная связь между ApplicationInstance и FunctionalityStatus (упомянутая в первом случае), почему мы не можем увидеть ее в базе данных?
    • Снова избыточность данных, потому что все записи ApplicationInstance видны (или должны быть) в таблице FunctionalityStatus.

Или, может быть, весь дизайн испорчен, и я должен придумать что-то совсем другое?


person ssobczak    schedule 22.02.2010    source источник
comment
Связан ли статус функциональности с каждым экземпляром приложения или с конкретным приложением? Итак, если один экземпляр приложения не работает, вы считаете, что все приложение не работает или только один конкретный экземпляр? Можете ли вы также объяснить, что будет включено в таблицы функциональных возможностей? Некоторые данные могут помочь увидеть, как они используются   -  person Waleed Al-Balooshi    schedule 23.02.2010


Ответы (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)
    );
person markusk    schedule 23.02.2010

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

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

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

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

person David Parvin    schedule 22.02.2010
comment
Спасибо за помощь, но я думаю, что вы неправильно поняли мой вопрос. Я разместил изображение, содержащее более подробную информацию, возможно, это прояснит вопрос. - person ssobczak; 23.02.2010

Если бы это был я, я бы сделал так:

  1. Создайте 5 таблиц: Machine, Application, Functionality, ApplicationPool и Log.
  2. Поместите столбец FK в Функциональность, который является идентификатором Приложения, для которого существует Функциональность.
  3. ApplicationPool будет иметь столбец идентификатора машины, столбец идентификатора приложения, первичный ключ, который является либо GUID, либо начальным идентификатором, идентификатор ApplicationInstance, который будет вашим ApplicationName + PK. Если вы можете, я бы использовал это, чтобы назвать ваши приложения вашими машинами.
  4. Наконец, я бы сделал таблицу журнала и дал столбец FK, который ссылается на PK ApplicationPool. Затем каждый раз, когда вы что-то записывали, вы могли добавлять это в таблицу Log, и вся ваша информация о приложении будет храниться отдельно.

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

person Ben Hoffman    schedule 22.02.2010
comment
Это часть решения, но вы пропустили часть о двух таблицах журналов. Я разместил изображение, возможно, оно будет более информативным, чем слова. - person ssobczak; 23.02.2010