Стоит ли создавать отдельные таблицы для разных видов продукции?

25

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

Типы продукции: модели, детали, комплекты запасных частей и опции.

Вариант A (первый дизайн): я планировал иметь отдельные таблицы для указанных выше типов продуктов. Я бы сказал, что около 75% полей будут одинаковыми в каждой таблице.

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

Вариант B: вместо отдельных таблиц я мог бы создать таблицу с именем Product, которая включает модели, детали, комплекты запасных частей и опции. Я мог бы иметь одно поле с именем type, чтобы различать модель, опции и т. Д. Я предполагаю, что недостатком является то, что несколько полей никогда не будут использоваться (оставлены пустыми) для определенных типов продуктов. Я предполагаю, что именно здесь "не лучшие практики" вступят в игру ..

Вариант B значительно уменьшит сложность дизайна БД. Мне также не пришлось бы беспокоиться о ссылках на кучу таблиц при извлечении данных для запросов ...

payling
источник
2
На этом этапе я предлагаю вам создать электронные таблицы, которые имитируют макет вашей таблицы и заполняют их данными. Это разоблачит любые слабости, которые могут существовать.
Майкл Райли - AKA Gunny
Как вы будете указывать внешние ключи на разные продукты, если они находятся в разных таблицах? Читайте о наследовании таблицы, пожалуйста.
Нил Макгиган

Ответы:

8

Если бы это было мое дизайнерское решение, я бы, вероятно, выбрал больше «Вариант C» (модифицированный вариант a).

Во-первых, почему бы не «Вариант B»:

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

С другой стороны, стратегия индексирования всегда требует, чтобы это поле типа было указано в списке. Так как это всего 4 типа, количество элементов индекса крайне низкое ( SELECT * FROM product_table WHERE type='X'в любом случае, в основном выполняется полное сканирование таблицы)

Вариант С

  • Создайте родительскую таблицу, которая содержит только столбцы, которые разделяют все типы
  • Создайте каждый тип продукта как отдельную таблицу со своими отдельными столбцами, с одним дополнительным: ссылка на родительскую таблицу
  • Создайте каждую таблицу ссылок: Product_Option, Model_option и т. Д. Со ссылками на соответствующие ключи.
  • Для тех, у кого есть взаимные ссылки (MODEL_OPTION, OPTION_MODEL), также создайте эти таблицы. Это добавит ясности в ваши объединения для всех, кто на это смотрит.

Недостатком является сложность обеспечения того, чтобы избегать сирот при обновлении / удалении объектов, и первоначальная разработка запросов, использующих эти таблицы.

Дерек Дауни
источник
5
Сейчас есть только 4 типа, но что, если больше будет добавлено позже? Я уверен, что главная таблица продуктов Amazon изначально называлась «Книги», но вы думаете, что у них есть отдельная таблица для каждого типа продукта сейчас? Я не думаю, что у каждого типа должна быть своя собственная таблица, но вы можете использовать модель EAV для дополнительных свойств, которые могут быть общими для каждого типа.
Аарон Бертран
1
@ Аарон Справедливое замечание о будущем увеличении типов продуктов. Если бы этот сценарий мог предположительно расшириться до 10+ типов продуктов, я бы пересмотрел. Но я считаю, что конкретные таблицы продуктов - это правильный выбор дизайна для небольшого количества типов продуктов.
Дерек Дауни
1
Вариант C: Нужно ли иметь таблицу ссылок? Я предположил бы, что PK Product_Option будет соответствовать PK таблицы Product, и это создаст ассоциацию для связи обеих таблиц.
Выплата
Используя Product_option в качестве примера, схема будет (на мой взгляд): id, productID, optionID. productIDбудет FK для product.id, и optionIDявляется FK для option.id. Вот что я имел в виду под таблицей ссылок. И да, в этом проекте необходимо разрешить одному продукту ссылаться на несколько вариантов.
Дерек Дауни
Хорошо я понял. Я неправильно понял, что вы напечатали .. Ой.
Выплата
7

Я бы посоветовал вам начать с «правильной» реляционной модели, вашего варианта А. Если типичное использование этой модели ведет вас к денормализации в некоторых областях, не бойтесь делать это.

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

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

Марк Стори-Смит
источник
2

Это звучит очень похоже на Bills материалов / нескольких кардинальностей heirarcy , что Пол Нильсен описывает в главе 17 из SQL Server 2008 Библии .

Вся глава очень хорошо прочитана, а конкретный раздел, посвященный вашей проблеме «многие ко многим», можно найти на страницах 416–419.

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

Майкл Райли - AKA Gunny
источник
Это решение выглядит аналогично варианту B (если я правильно понимаю, что я не уверен, что я понимаю). У меня была бы основная таблица (Products) и таблица «link» (также называемая смежной таблицей / BillsofMaterials) для создания связей между моделями, опциями, наборами и т. Д. Это правильно?
Payling
Я думаю, что проблема затуманена из-за вариантов. Давайте возьмем варианты из обсуждения на некоторое время. Части самые маленькие. Группа деталей составляет модель. Группа запасных частей в форме комплекта составляет подмножество модели. Все идет нормально. Теперь у деталей есть опции, для простоты предположим, что это включает две категории: цвет (черный, красный, хром) и материал (металл, дерево, пластик). Вы также упомянули, что у моделей есть варианты. Параметры модели отделены от параметров детали или модели кажутся имеющими только варианты, потому что детали отличают модели?
Майкл Райли - AKA Gunny
Запчасти не имеют «вариантов» в моем дизайне. Я определяю опцию как нечто, что входит в модель, которая предоставляет ему расширенную функциональность. Опция состоит из частей. Модель может иметь много разных вариантов. Опция может подходить для многих моделей.
оплата
Это не так, как вы сформулировали свой вопрос. Цитата: «Например, у Модели может быть много опций, а у опции может быть много моделей. У опции также может быть много деталей, и у детали может быть много опций ... и так далее ..." В этом пункте я предлагаю вам создавать электронные таблицы, которые имитируют макет вашей таблицы и заполнять их данными. Это разоблачит любые слабости, которые могут существовать.
Майкл Райли - AKA Gunny
0

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

Вместо того, чтобы оставлять много неиспользуемых пустых полей в таблице Product, почему бы не добавить таблицу ModelProduct, таблицу PartProduct, таблицу ReplacementPartKitProduct и иметь только те поля, которые различны для этих типов в этих таблицах? Используйте для этих таблиц тот же первичный ключ, что и для таблицы Product. Присоединитесь к таблице Product и ModelProduct, если вы хотите работать с моделями. Нужно определить, является ли запись Продукта вашей Частью? Просто выполните левое соединение между Product и PartProduct, и если PartProduct. [PrimaryKey] не равен NULL, у вас есть деталь. Если это ноль, это не часть. Кроме того, вы можете добавить поле ProductType в таблицу Product.

Алан Макби
источник
Пустые поля будут минимальными, потому что примерно 75% полей будут использоваться в каждой таблице. Думаю, меня больше беспокоит связь между типами продуктов. У меня будет три или около того таблицы ссылок, указывающих на одну и ту же таблицу. Model_has_Option два первичных ключа, оба идентификатора продукта таблицы продуктов, если бы я использовал только одну таблицу для представления типов продуктов. Меня больше волнует, правильно ли это делать или нет.
выплаты
Хотя существует много факторов, которые влияют на «правильное» решение, необходимо учитывать два основных фактора. 1: общие требования к производительности; 2: адаптивность / сложность / ремонтопригодность. Один из этих двух, вероятно, немного важнее другого. Если вам нужна скорость, денормализуйте, придерживаясь варианта А. У вас будет дублирование; это ожидается. Если вам нужно регулярно работать со схемой, а скорость - это НЕ САМЫЙ важный фактор, тогда Вариант B. Вы понимаете это «правильно», зная свои приоритеты, а не придерживаясь «чужих лучших практик».
Алан Макби