Отношения многие ко многим в проектировании баз данных - PullRequest
4 голосов
/ 28 октября 2010

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

создать настольный станок ( номер машины, machine_name char (30) )

создать часть таблицы ( номер part_id, part_name char (30) )

создание табличных отношений ( номер part_id, номер машины )

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

Спасибо.

Ответы [ 6 ]

8 голосов
/ 28 октября 2010

Добро пожаловать в реляционные базы данных.Нет, лучшего способа нет.Я бы посоветовал назвать ваши таблицы немного лучше;Machine, Part, Machine_Part или что-то в этом роде, потому что вы, вероятно, в конечном итоге получите множество таких таблиц.эти отношения, используя простые ВНУТРЕННИЕ СОЕДИНЕНИЯ в SQL или используя ORM.Базы данных рассчитаны на такие вещи.

4 голосов
/ 29 октября 2010

Отредактировано для улучшения ясности

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

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

Несколько вещей, которые нужно понять, прежде чем мы пойдем на погоню.

  1. По вашему описанию, машины на самом деле являются сборками (частей). Эти сборки используются в сборках (более высокого уровня) и так далее. Итак, давайте переименуем «отношения» в сборку.

  2. Ваши таблицы деталей и машин не были нормализованы. Если вы внимательно осмотрите их, вы найдете много одинаковых столбцов (показаны PartId :: MachineId, PartName :: MachineName). Фактически за исключением самой низкой части машины и самой высокой части, содержащей машины, все промежуточные машины (содержащие детали) фактически являются также деталями в машинах (более высокого уровня). Итак, у вас чудовищное дублирование данных. Это большая ошибка нормализации. Это убьет производительность. Получающиеся в результате аномалии обновления вызовут проблемы целостности данных. обе эти проблемы выйдут на передний план задолго до того, как решат ваши другие проблемы.
    .
    Так что это должно быть исправлено обычным процессом нормализации: деталь и машина становятся одной таблицей: деталь. Тот факт, что деталь может быть сборкой (компонентов), основан на контексте использования; тот факт, что деталь может быть компонентом (в сборках), также основан на контексте. Как единое целое, лежащее на полке, инвентарь которого вы должны хранить, Детали и Машины являются просто Частями. Столбцы управления запасами расположены в Части; столбцы контекста расположены в сборке.

  3. Отношения «многие ко многим» (логически они являются отношениями, а не таблицами) реализуются на физическом уровне в виде ассоциативных таблиц, обходных путей нет. У вас уже есть это. То, что вы собираетесь увидеть, может выглядеть иначе, но это не так.

Все, что вы получите от меня, будет 5NF; нулевое дублирование данных; Нулевое обновление Аномалии. Это работает в производстве более чем на нескольких производственных площадках. Случилось так, что я использую требуемую структуру как часть учебника в моих продвинутых классах, так что вы можете просто посмотреть ее. Не стесняйтесь задавать любые вопросы, связанные с пониманием или иным образом. Именно в учебнике именно потому, что многие разработчики не понимают структуру или как перемещаться по ней. Обратите внимание на очень жесткие (проверенные и проверенные) соглашения об именах.

Нажмите на Деталь или Сборка (вы можете игнорировать остальную часть Модели, но я также с удовольствием отвечу на вопросы об этом). И методология, и обозначение диаграммы - это IDEF1X (это «строгое» представление RM).

Пример компонента сборки детали

И да, целостность данных поддерживается, и Assembly⇢ Поиск компонентов выполняется на 100% (с учетом покрытых запросов) из индекса первичного ключа сборки (то есть они уже высоко оптимизированы). Мне не нужно делать из них тех или иных продавцов, чтобы получить от этого больше скорости). Второй уникальный индекс обслуживает поиск компонентов - сборка 100%.

Наслаждайтесь.

3 голосов
/ 30 октября 2010

Краткий ответ: Вы движетесь в правильном направлении. Это учебный способ создания отношений «многие ко многим».

Однако «машина», вероятно, является просто частным случаем «детали», а именно, той части, которую вы в некотором смысле считаете «законченной вещью» или предметом поставки.

Большинство людей, которые делают это, создают иерархическую структуру. У вас есть:

part(part_id, description, ... maybe other data like size and weight, etc ...)
assembly(parent_part_id, child_part_id)

Тогда деталь верхнего уровня может иметь много составных частей, и каждый из этих компонентов может иметь другие компоненты и т. Д. Преимущество этого состоит в том, что когда сборка используется более чем в одном конечном продукте, вам нужно только прорыв один раз. Например, я работал в компании, которая производила посудомоечные машины. В таблице деталей у нас будет запись, скажем, для модели двигателя 29B. Этот двигатель будет состоять из множества составных частей - корпуса, ротора, статоров, электропроводки и т. Д. Но один и тот же двигатель может использоваться в нескольких разных моделях посудомоечной машины. Вам не нужно заново указывать полный список деталей для двигателя для каждой посудомоечной машины, на которой он используется. Мало того, что кому-то неудобно печатать, но если вы когда-либо вносите изменения, вы должны быть уверены, что изменяете их везде, где они используются. Таким образом, вы просто даете один раз пробой для двигателя, а затем ссылаетесь на двигатель как на единицу во всех сборках более высокого уровня.

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

Запчасти есть части. Положите их все в один стол.

Некоторые движки баз данных, например Oracle, есть команды, чтобы преследовать иерархию, как это. Если у вас нет, вам придется сделать это в коде. Но это не так сложно. Люди делают это постоянно.

3 голосов
/ 28 октября 2010

Это не наивно, это правильный способ модели ER. Разделение сущностей с помощью отношений, классический дизайн шаблона. Не беспокойтесь о затратах на запрос / соединение, СУБД оптимизированы для этого и могут выполнять эти запросы на соединение.

Вы также можете сделать таблицу отношений (part_id, machine_id) в качестве составного первичного ключа. А еще лучше, создайте их как индексированные организованные таблицы и избегайте (незначительных) накладных расходов на данные таблиц.

2 голосов
/ 28 октября 2010

Четкий способ думать об этом: логический против физического

Логическое отношение «многие ко многим» между двумя объектами (назовите их A и B) имеет физическую реализацию трех таблиц (назовите их A, B и C). Эта реализация включает в себя физическое отношение «один ко многим» от A до C. Другое от B до C. Таблица C известна как «таблица соединений» или «таблица соединений»

2 голосов
/ 28 октября 2010

Это нормализованные данные - наиболее масштабируемый способ хранения любой комбинации записи part в записи machine.

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

Обработайте проблему, когда она действительно возникнет - в противном случае это преждевременная оптимизация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...