Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.06.14;
Скачать: [xml.tar.bz2];

Вниз

Проектирование БД   Найти похожие ветки 

 
DynaBlaster   (2009-04-09 19:22) [0]

Есть два вида принципиально разных устройств.

Допустим, один тип обладает характеристиками: "a", "b" и "c".
Второй тип обладает: "d", "e" и "f".

Информацию об устройствах нужно хранить в БД, при этом у каждого устройства конкретного должен быть свой индивидуальный ID, также у устройств есть имена. Как лучше это делать, в каких таблицах?

Мои варианты:

1) в одной таблице с полями:

ID, Name, TypeDevice, a, b, c, d, e, f

самое простое решение, но в такой таблице всегда есть избыточные поля

2) в двух таблицах:

Первая: ID, Name, a, b, c
Вторая: ID, Name, d, e, f

Избыточности нету, зато более сложная работа по обеспечению уникальности ID в РАЗНЫХ таблицах. Выборка более сложная по логике: например, чтобы найти устройство по ID надо посмотреть в одну таблицу, если нету - то в другую...

3) хранить в трех таблицах:

Первая: ID, Name, TypeDevice

Вторая: REF_ID, a, b, c
Третья: REF_ID, d, e, f

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

Какой вариант выбрали бы вы и почему? Возможно, какие-то другие варианты?

P.S. Возможно, хотя и вряд ли, что добавится какой-нибудь еще один принципиально новый тип устройств. В этом вариант 1, конечно, сильно проигрывает.


 
DVM ©   (2009-04-09 19:39) [1]


> DynaBlaster   (09.04.09 19:22)  

Достаточно таблицы DEVICE_ID DEVICE_TYPE DEVICE_NAME ПОЛЕ С ПРОЧЕЙ ЛАБУДОЙ ХАРАКТЕРНОЙ ДЛЯ КОНКРЕТНОГО ДЕВАЙСА


 
DVM ©   (2009-04-09 19:41) [2]

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


 
palva ©   (2009-04-09 19:45) [3]

Если объем данных большой, (а для чего тогда БД?), то однозначно третий.
Почему? Потому что это стандартный способ, который понятен и привычен специалистам по БД, и данные в этом виде все движки SQL умеют эффективно обрабатывать. Только надо еще правильно создать индексы.
А "выборка не самая тривиальная", это зря. Хотя бы год попишете запросы - и будете писать такое автоматом.


 
oxffff ©   (2009-04-09 19:46) [4]


> DynaBlaster   (09.04.09 19:22)  


google отношение супертип подтип реляционные СУБД


 
oxffff ©   (2009-04-09 19:47) [5]

или с точки зрения корректности проектирования это вариант 3.


 
oxffff ©   (2009-04-09 19:47) [6]

или с точки зрения корректности проектирования это вариант 3.


 
DVM ©   (2009-04-09 19:52) [7]

Если будут постоянно добавляться новые типы устройств 3 вариант станет очень неудобен.


 
Ega23 ©   (2009-04-09 19:58) [8]


> Если будут постоянно добавляться новые типы устройств 3
> вариант станет очень неудобен.


Зависит от СУБД. В Postgres с его наследованием таблиц - очень даже удобен.


 
palva ©   (2009-04-09 20:08) [9]

А если так сделать:
Первая: ID, Name, TypeDevice
Вторая: ID, характеристика значение
Одной строке первой таблицы соответствуют несколько строк второй.
Только теперь отсутствует информация о том, какие характеристики присутствуют в том или ином типе устройства. Кроме того все значения характеристик должны иметь один тип, например, строковый.


 
Игорь Шевченко ©   (2009-04-09 20:09) [10]


> Допустим, один тип обладает характеристиками: "a", "b" и
> "c".
> Второй тип обладает: "d", "e" и "f".
>
> Информацию об устройствах нужно хранить в БД, при этом у
> каждого устройства конкретного должен быть свой индивидуальный
> ID, также у устройств есть имена. Как лучше это делать,
> в каких таблицах?


1. (DEV_TYPE_ID, прочая лабуда типа)

2. (DEV_ID, DEV_TYPE_ID, DEV_NAME, прочая лабуда устройства)

3. (DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)


 
palva ©   (2009-04-09 20:10) [11]

Для запроса применяется обычное соединение таблиц, никаких вложенных запросов.


 
oxffff ©   (2009-04-09 20:16) [12]


> palva ©   (09.04.09 20:08) [9]


К вашему решению добавить

Для очень крутых ребят

1. еще есть метатаблица с описание характеристик для каждого типа.
2. Добавить таблицы
 
  характеристика_ID, тип значение целое
  характеристика_ID, тип varchar
  характеристика_ID, тип blob
  .....
3. в вашу таблицу
  Вторая: ID, характеристика значение добавить
 преобразовать к виду

 характеристика_ID,ID, характеристика_type_id, value_type
4. Где value_type справочник поддерживаемых типов из пункта 2.


 
oxffff ©   (2009-04-09 20:19) [13]


> oxffff ©   (09.04.09 20:16) [12]


Это решения для характеристик плавающего типа. То есть можем задать значение одной и той же характеристики разными типами.

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


 
int64   (2009-04-09 20:21) [14]

palva ©   (09.04.09 20:08) [9]
Игорь Шевченко ©   (09.04.09 20:09) [10]
oxffff ©   (09.04.09 20:16) [12]

Это предполагает, что тип характеристики может быть сущностью.
Автор такого не говорил.


 
oxffff ©   (2009-04-09 20:23) [15]


> int64   (09.04.09 20:21) [14]


На этом форуме обычно мало интересует то, что спрашивает автор.
:)


 
Игорь Шевченко ©   (2009-04-09 20:28) [16]

int64   (09.04.09 20:21) [14]


> Это предполагает, что тип характеристики может быть сущностью.


Что есть характеристика, если не сущность, тем более, в данном контексте ?


 
palva ©   (2009-04-09 20:43) [17]


> Автор такого не говорил.

Автор неосторожно проронил: "Возможно, какие-то другие варианты?"


 
int64   (2009-04-09 21:03) [18]

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


 
Игорь Шевченко ©   (2009-04-09 21:09) [19]


> Я мел ввиду, что характеристика может и не быть простым
> аттрибутом


а какая собственно разница ?


 
int64   (2009-04-09 21:48) [20]

Да нет разницы.
У одного девайса характкристики - лог счетчиков, у другого - цена и производитель.
Автор же не сказал, что логически характеристики можно представить одной сущностью. (хотя, наверно, это и подразумевал)
А физически что-угодно можно скрутить.


 
Ping-Pong   (2009-04-09 22:04) [21]

>>> Игорь Шевченко ©   (09.04.09 21:09) [19] а какая собственно разница ?

Давай все хранить в бинарном потоке, а?


 
DynaBlaster   (2009-04-10 12:31) [22]


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


интересная идея.. Типа как GET-параметры:

ParamName1=ParamValue1&ParamName2=ParamValue2&...

Но добавляется постоянный парсинг (по скорости это не критично). Не очень хороший подход, имхо, для БД, где один из смыслов это структурирование типов данных.


> Если объем данных большой, (а для чего тогда БД?),

объем данных совершенно небольшой. БД потому что сама структура данных и работа с ними очень коррелирует с принципами БД.
У каждого устройства должен быть уникальный идентификатор, работа с устройством идет по этому идентификатору - запрос данных, удаление устройства и так далее. Можно реализовать и на INI-файлах, но придется фактически реализовывать мини-БД.
Впрочем, если ты расскажешь как без БД сделать все тоже самое -интересно.

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


> Если будут постоянно добавляться новые типы устройств 3
> вариант станет очень неудобен

да. Но варианты 1-2 будут не менее неудобными.


> Первая: ID, Name, TypeDevice
> Вторая: ID, характеристика значение
> Одной строке первой таблицы соответствуют несколько строк
> второй.
> Только теперь отсутствует информация о том, какие характеристики
> присутствуют в том или ином типе устройства. Кроме того
> все значения характеристик должны иметь один тип, например,
>  строковый.


интересно, но мне кажется не для этого случая.


> 1. (DEV_TYPE_ID, прочая лабуда типа)
> 2. (DEV_ID, DEV_TYPE_ID, DEV_NAME, прочая лабуда устройства)
> 3. (DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)


вы что-то не поняли. Предложенная структура не позволяет решить проблему, описанную в сабже.

Пример: у одного из типов устройств есть характеристика порт, она может изменяться в большом диапазоне 1-65 тысяч, а у других устройств данной характеристики просто нету.


 
Игорь Шевченко ©   (2009-04-10 13:11) [23]


> Пример: у одного из типов устройств есть характеристика
> порт, она может изменяться в большом диапазоне 1-65 тысяч,
>  а у других устройств данной характеристики просто нету


3. (DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)

значит для типа DEV_TYPE_ID такой характеристики не будет у тех типов устройств, где порт отсутствует.


 
Труп Васи Доброго ©   (2009-04-10 13:24) [24]

У меня реализуется такой вариант:
1 "сборная" таблица устройств ID, Name, TYPE_ID
2 Таблица типов устройств TTPE_ID, TYPE_NAME, TYPE_TABLE NAME
3 собственно сами таблицы по одной для каждого вида устройств  ID, property1, property2..., причём имя каждой таблицы записано во второй таблице как TYPE_TABLE NAME.
Такая структура даёт универасльное решение при заранее неизвестном количестве типов устройств и их характеристик.
Таблица под новый тип создаётся автоматически с указанным набором свойств.
Проблем с уникальностью ID в разных таблицах нет в принципе, используется один генератор для всех таблиц.
ИМХО просто и гениально. :)


 
Sergey13 ©   (2009-04-10 15:45) [25]

> [0] DynaBlaster   (09.04.09 19:22)

Прочитал по диагонали пунктиром, сори если повторю кого то.

Я бы попробовал реализовать так.
1. Типы устройств(ИД, Имя, все остальные дела)
2. Характеристика (ИД, Тип_ИД, Имя, все остальные дела)
3. Устройства (ИД, Имя, Тип_ИД, все остальные дела)
4. Характеристики устройств (ИД, Устройство_ИД, Характеристика_ИД, значение)


 
Игорь Шевченко ©   (2009-04-10 18:26) [26]

Sergey13 ©   (10.04.09 15:45) [25]

Характеристика есть свойство типа, насколько я понял.
То есть, тип устройства уже определяет набор его характеристик


 
Городской Шаман   (2009-04-10 18:33) [27]


> DynaBlaster   (09.04.09 19:22)  


Как вариант - в записи хранить общее описание устройства(идентичное для всех, по типу название, тип и прочее) и дополнительное поле типа blob в котором хранить xml-описание конкретных характеристик устройства.


 
kaif   (2009-04-10 18:45) [28]

Из предложенных трех вариантов третий - наилучший.

Добавлю еще один вариант. С наследованием.

Допустим имеются два вида устройств, у которых есть общие параметры (a,b). То есть два вида устройств характеризуются так:
a,b,c,d
a,b,e,f,g

Тогда делаем 4 таблицы:

id, class_id, name
id, a, b
id, c, d
id, e, f, g

Для созания экземпляра  устройства нужно добавить запись с одинаковым id в 3 таблицы.
Это полная нормализация.
Предельная.
У меня так устроены справочники в финансовой системе Allegro.
Удобно, если поле name - сборное наименование. И способ сборки зависит от класса. При добавлении устройства первого типа name собирается из параметров a,b,c,d, а при добавлении устройства второго типа - из a,b,e,f,g. У меня сборка имен происходит автоматически при помощи хранимых процедур, тексты которых также генерируются автоматически на основе "шаблонов построения имен", которые у каждого класса свои.

При такой организации если нужен просто список устройств, можно вывести какие-то записи из первой таблицы. В первой таблице можно искать в поле name и при помощи запросов с использованием LIKE. Если же нужно строго сгруппировать по каким-то полям, то тогда уже делаются объединения 3 таблиц и мы получаем полную таблицу для отдельно взятого класса.

Допустим, у все электробытовые устройства имеют "потребляемую мощность". Но лишь стиральные машины имеют "частоту оборотов отжима". В случае 3 таблиц (как в сабже) не ясно, где должно находиться поле "потребляемая мощность". В случае же с наследованием (как в моих справочниках) это поле должно находиться в таблице собственных атрибутов "класса предка" для всех устройств, наследующих этому классу.
Условно так, например:

1. Устройства(id, calss_id, name)
2. Бытовые приборы(id, "потребляемая мощность")
3. Телевизоры(id, "размер экрана", "разрешение по вертикали", "разрешение по горизонтали")
4. Стиральные машины

Чтобы выбрать все атрибуты телевизоров, объединяем таблицы 1,2,3
А чтобы выбрать все стиралки, объединяем талицы 1,2,4
А чтобы найти все приборы, потребляющие менее 500 ватт, объединяем лишь таблицы 1 и 2 по условию "потребляемая мощность" < 500, и смотрим поле name.

Четвертая нормальная форма. Если не пятая. :)
Для фанатов нормализации, так сказать.


 
kaif   (2009-04-10 19:04) [29]

Но увлекаться многоуровневым наследованием (сверхнормализацией) я не рекомендую. Если нет серьезных причин, проще сделать вариант 3 сабжа.

То есть отдельные таблицы с собственнымим атрибутами и первую денормализацию: "таблицу-реестр ID всех объектов". Вот сборку наименований в "реестре" рекомендую всячески. А наследование (хотя я его иногда и применял) редко оправдывает затраты. Так как мало кому бывают нужны запросы вида "все бытовые приборы, мощностью до 500 W.

Идеальное устройство справочников (с учетом моего опыта работы в системе Allegro, позволяющей добиваться высокой степени нормализации) должно быть таково (это наилучший компромисс):

1. Атомарные спрачоники низшего уровня (Страны, Города, единицы измерения, стандартные литражи бутылок, стандартные разрешения экранов телевизоров, и прочее), в основном такие справочники имеют структуру id, code, name.

2. Строгие справочники постоянных объектов (в данном случае - устройств), в основном содержащие ссылки на id атомарных справочников и имеющие множество полей (как правило до 10).

3. Реестр для постоянных объектов - денормализация строгих справочников в простое поле name (сборное наименование в виде строки), имеет обычно id, class_id, name.

4. Накопители для данных (заказы, продажи и т.п.). Обычно это двухуровневые связки таблиц Master-Detail, опирающиеся на атомарные справочники и справочники постоянных объектов. Часто имеют кучу полей. Нужных и не очень.

5. Денормализованные реестры для накопителей (журналы проводок, журналы документов и т.п.). Их следует тщательно продумывать.

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


 
b z   (2009-04-11 11:33) [30]


> Sergey13 ©   (10.04.09 15:45) [25]
Если 1 и 2 "перевязать" как многие ко многим, то еще универсальнее будет.


 
DynaBlaster   (2009-04-11 11:43) [31]

Игорь Шевченко ©   (10.04.09 13:11) [23]
3. (DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)

значит для типа DEV_TYPE_ID такой характеристики не будет у тех типов устройств, где порт отсутствует.


ну это понятно.
Непонятно, где в такой структуре писать само значение порта конкретного устройства?

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

>3. (DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)

а

>3. (DEV_ID, DEV_TYPE_ID, имя_характеристики, прочая лабуда характеристики)

Ну а на самом деле DEV_TYPE_ID тогда избыточен и:

>3. (DEV_ID, имя_характеристики, прочая лабуда характеристики)

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

kaif, спасибо, я понял.

Городской Шаман   (10.04.09 18:33) [27]
Как вариант - в записи хранить общее описание устройства(идентичное для всех, по типу название, тип и прочее) и дополнительное поле типа blob в котором хранить xml-описание конкретных характеристик устройства


ну это уже предлагал DVM в [2]


 
kaif   (2009-04-11 12:11) [32]

решение Sergey13 ©   (10.04.09 15:45) [25]  хорошо, если характеристик немного. Если их, к примеру 20 в каком-то классе, то для того чтобы получить "полную картину" нужен запрос с 20-кратным объединением. Это может привести к тормозу.

И это было бы еще ничего, если бы не проблема NULL-полей.

На уровне базы данных обеспечить целостность данных при вертикальной записи параметров сложно.

Допустим какой-то параметр отсутствует (строка удалена). Если запросы устроены как внутренние объединения, устройство просто будет потеряно. А если запросы будут устроены как внешние объединения, то велик риск других неприятностей. Допустим, отсутствует параметр "Масса, кг" у какого-то устройства. А приложение собирается просуммировать вес партии товара для отправки курьерской службой. При внешнем объединении под агрегатной функцией SUM() окажется значение NULL и результат будет некорректным либо сервер вообще сообщит об ошибке.

Следовательно к разработчику приложений предъявляется куча требований при подобном "вертикальном" хранении:

1. Запрет на внутренние объединения
2. Принудительное использование проверки на NULL во всех агрегатах. Наподобие SUM(CASE MYFIELD IS NULL THEN 0 ELSE MYFIELD END)

Теперь рассмотрим запрос, в котором в условии WHERE нужно обеспечить устройства "с массой менее 0,5 кг". В этом случае проблема NULL потребует соблюдение условия 2. не под агрегатом, а в условии WHERE. Однако и этого недостаточно. Так как если мы использовали условие 2. и нашли все устройства, у которых масса менее 0,5 кг таким способом, то в набор попадут как те устройства, у которых масса менее 0, 5 кг, так и те, у которых масса отсутствует вообще (нет такой записи). И каждый раз придется об этом думать. И требовать, чтобы пользователь различал "отсутствие массы" от "массы 0". Либо нужно в триггерах обеспечить проверку со сканированием вплоть до 20 строк, что делает систему сильно платформозависимой и вовсе не столь простой, как она кажется на первый взгляд.

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



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2009.06.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.005 c
11-1201359442
Elec3C
2008-01-26 17:57
2009.06.14
Вопрос по Button у


2-1240890718
гранит
2009-04-28 07:51
2009.06.14
Вопрос


2-1240689147
Ramil
2009-04-25 23:52
2009.06.14
combobox


15-1238445234
Дмитрий Белькевич
2009-03-31 00:33
2009.06.14
Вопрос по дедлокам.


15-1239134355
istok
2009-04-07 23:59
2009.06.14
восстановить delphi...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский