База данных "supertable" и больше таблиц против общей таблицы
Я пытаюсь определить дизайн базы данных. В частности, это часть более крупного дизайна. В принципе, есть "местоположения" - каждое место может иметь любое количество связанных с ним датчиков, и оно может иметь регистратор (но только 1).
У меня есть показания датчика, и у меня есть показания регистратора, каждый из которых достаточно разный, чтобы оправдать отдельные таблицы.
Если показание датчика выходит за пределы диапазона, генерируется предупреждение. В то время как показания датчика остаются вне диапазона, они продолжают связываться с этим предупреждением, поэтому вы получаете 1 предупреждение, содержащее множество показаний, что позволяет мне позже отображать предупреждение, чтобы я мог определять тенденции и т.д.
То же самое с показаниями журнала.
Вот мои 3 идеи для хранения этих данных:
Вариант 1:
Location [Table]
- Id [PK]
- Name
- HasLogger
LiveSensor [Table]
- LocationId [FK]
- Id [PK]
LiveSensorReading [Table]
- Id [PK]
- SensorId [FK]
- Value
LiveSensorAlert [Table]
- Id [PK]
- SensorReadingId [FK] (may not be needed - enforces need to always have at least 1 reading)
LiveSensorAlertCorrectiveAction [Table]
- LiveSensorAlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]
LiveSensorAlertAcknowledgement [Table]
- LiveSensorAlertId [FK]
- ByUserID [FK]
LiveSensorAlertReading [Table]
- SensorAlertId [FK]
- SensorReadingId [FK]
LoggerReading [Table]
- LocationId [FK]
- Value
LoggerAlert [Table]
- Id [PK]
- LoggerReadingId [FK] (may not be needed - enforces need to always have at least 1 reading)
LoggerAlertReading [Table]
- LoggerAlertId [FK]
- LoggerReadingId [FK]
LoggerAlertCorrectiveAction [Table]
- LoggerAlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]
LoggerAlertAcknowledgement [Table]
- LoggerAlertId [FK]
- ByUserID [FK]
- Проблема: много повторяющихся таблиц (действительно ли это имеет значение, хотя?)
Вариант 2:
Location [Table]
- Id
- Name
- HasLogger
Sensor [Table]
- Id [PK]
- LocationId [FK]
SensorReading [Table]
- Id [PK]
- SensorId [FK]
- Value
LoggerReading
- LocationId [FK]
- Value
Alert [Table]
- Id [PK]
AlertCorrectiveAction [Table]
- AlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]
AlertAcknowledgement [Table]
- AlertId [FK]
- ByUserId [FK]
SensorAlertReading
- AlertId [FK]
- SensorReadingId [FK]
LoggerAlertReading
- AlertId [FK]
- LoggerReadingId [FK]
- Проблема: не применяет "по крайней мере 1
чтение на предупреждение ".
- Проблема: позволяет использовать несколько типов
чтение для ссылки на одно и то же предупреждение.
Вариант 3:
Location [Table]
- Id
- Name
- HasLogger
Sensor [Table]
- Id [PK]
- LocationId [FK]
SensorReading [Table]
- Id [PK]
- SensorId [FK]
- Value
LoggerReading
- LocationId [FK]
- Value
Alert [Table] "super table"
- Id [PK]
LoggerAlert [Table]
- AlertId [PK, FK]
- LoggerReadingId [FK]
SensorAlert [Table]
- AlertId [PK, FK]
- SensorReadingId [FK]
AlertCorrectiveAction [Table]
- AlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]
AlertAcknowledgement [Table]
- AlertId [FK]
- ByUserId [FK]
SensorAlertReading [Table]
- SensorAlertId [FK]
- SensorReadingId [FK]
LoggerAlertReading [Table]
- LoggerAlertId [FK]
- LoggerReadingId [FK]
- Проблема: ничто не останавливает
LoggerAlert и SensorAlert
ссылаясь на одно и то же предупреждение (та же проблема
как вариант 2).
- Проблема: Обфускация базы данных (не
супер таблица больше концепции OO?
база данных должна быть чисто
реляционная не так ли?)
Я думаю, что до сих пор я предпочитаю вариант 1, потому что он просто кажется таким чистым, и ясное намерение (я надеюсь!), хотя я эффективно повторяю таблицы.
Единственная небольшая проблема, о которой я только подумала, заключается в том, что показания для разных датчиков все еще могут быть связаны с одним сигналом тревоги.
Мне интересно, каковы мнения людей по вышеуказанным вариантам. Я видел, что использование "супер-таблиц" часто рекомендовалось, но по какой-то причине оно просто не кажется правильным - это почти похоже на взломы, особенно когда я вижу методы для обеспечения целостности данных. Это кажется более похожим на программирование OO, чем на реляционный дизайн.
Спасибо.
EDIT:
Дополнительная информация, чтобы помочь ответить на некоторые из следующих вопросов:
В большинстве случаев база данных обрабатывается только через сервер приложений, если это имеет какое-то значение.
Сигналы оповещений и оповещений в реальном времени, как правило, обрабатываются одинаково, поэтому я, скорее всего, буду иметь дело со всеми предупреждениями большую часть времени, вместо того, чтобы иметь дело с предупреждениями о регистрации и предупреждениями по-разному.
В журнале есть довольно конкретные столбцы, которые находятся в таблице местоположений. Поскольку местоположение и регистратор будут отображать от 1 до 1, я решил не иметь отдельную таблицу журналов, и до сих пор, как представляется, он был разработан и оставался простым. Примеры столбцов: LoggerRFID (int), LoggerUpperLimit (float), LoggerLowerLimit (float) и т.д. Вы могли бы почти утверждать, что регистратор - это датчик, но я пошел по этой дороге, и это не получилось слишком хорошо.
Я могу почти согласиться с созданием предупреждений общего характера, но, как сказал один из ответов, я стараюсь быть очень уверенным в этом, поэтому продолжаю исследование до тех пор, пока я могу, прежде чем выбрать конкретный путь.
Ответы
Ответ 1
Некоторые мысли (идеи и мнения, а не ответы) об этом:
Модель "supertable" (тип/подтип) является убедительной, но может быть сложной для реализации и поддержки. Несколько трюков:
ALERT
AlertId PK 1/2
AlertType PK 2/2 Check constraint (1 or 2, or better L or S)
... т.е. составной первичный ключ, где "тип" всегда должен быть L) og или S).
LOGALERT
LogAlertId PK 1/2 FK 1/2
AlertType PK 2/2 FK 2/2
(and again for SENSORALERT)
... то есть тот же самый составной первичный ключ, а внешний ключ находится в обеих столбцах. Сделанный таким образом, может быть только одна таблица подтипов для данной таблицы типов, а верхняя таблица четко показывает, какой подтип задействован. Никакой способ обеспечить соблюдение строки в таблице подтипов, поэтому тщательно настройте свои данные. И большую часть сложности запросов можно решить (скрыть?), Используя представления.
Недостатком является то, что он сложный, запутанный тем, кто еще не знаком с ним, и потребует дополнительной поддержки и усилий. Реальный вопрос: стоит ли это?
- Как часто вы должны иметь дело со всеми предупреждениями, а не только с журналом или только с датчиком? Если в большинстве случаев вам приходится иметь дело только с одним или другим, это, вероятно, не стоит.
- С какими деталями вы будете иметь дело с конкретными данными, зависящими от Log или Sensor? Помимо фактических событий, связанных с индивидуальным предупреждением, насколько похожими по обоим типам являются несметные атрибуты (детали в столбцах), которые вы будете отслеживать? Если пользователи, знания и корректирующие действия (достаточно) идентичны, вы можете сделать их атрибутами (столбцами) ALERT, но если нет, тогда вы должны сделать их atttributes соответствующего подтипа и потеряете преимущество консолидации супертипа.
- И вы должны получить его правильно сейчас, во время разработки. Научитесь, задавайте вопросы, смотрите на хрустальные шары (то есть размышляйте, что может произойти в будущем, чтобы аннулировать все текущие предположения), потому что, если вы ошибаетесь, вам и вашим преемникам, возможно, придется жить с ним навсегда.
Ответ 2
Вы можете добавить столбец ObjectType в свои зеркальные таблицы в первом варианте и предоставить значения как Sensor, так и Logger. Тогда ваш дизайн базы данных будет выглядеть примерно так:
Location [Table]
- Id
- Name
- HasLogger
ObjectType [Table]
- Id [PK]
- Name -- either Sensor or Logger
- Description
Object [Table]
- Id [PK]
- LocationId [FK]
- ObjectTypeId [FK]
Reading [Table]
- Id [PK]
- ObjectId [FK]
- Value
ObjectReading
- ObjectId [FK]
- ReadingId [FK]
Alert [Table]
- Id [PK]
- ReadingId [FK]
AlertCorrectiveAction [Table]
- AlertId [FK]
- CorrectiveActionId [FK]
- ByUserId [FK]
AlertAcknowledgement [Table]
- AlertId [FK]
- ByUserId [FK]
Эта конструкция немного запутывает базовую цель базы данных, в основном потому, что я не мог придумать лучшего слова для описания "датчика или регистратора", чем "объект" - если есть какой-то конкретный термин, который мог бы все вместе описать прикрепленный в месте, что, несомненно, облегчит понимание базы данных.
Вы также можете удалить столбец Идентификатор из ObjectType и сделать имя Первичным ключом, если вы не особенно брезгливы о нецелочисленных идентификаторах в таблицах. У меня были плохие впечатления от таблиц, таких как ObjectType, где первичный ключ не является целым числом, поэтому я почти всегда использую его.
Я также согласен с оценкой KM выше, что каждый идентификатор первичного ключа таблицы должен быть назван чем-то длиннее, чем "Id".
Ответ 3
Я думаю, на этот вопрос был дан ответ в другом вопросе с полной моделью данных; в противном случае (если есть что-то непогашенное), напишите "Редактировать" на этот вопрос.
Если вы заинтересованы в реляционной структуре Supertype-Subtype, в общем смысле, этот вопрос могут вас заинтересовать.
Могу предложить вам закрыть этот вопрос.