Укороченная версия
Мне нужно добавить фиксированное количество дополнительных свойств для каждой пары в существующем соединении «многие ко многим». Переходя к диаграммам ниже, какой из вариантов 1-4 является наилучшим способом с точки зрения преимуществ и недостатков, чтобы достичь этого путем расширения базового варианта? Или есть лучшая альтернатива, которую я здесь не рассматривал?
Более длинная версия
В настоящее время у меня есть две таблицы в отношении многие ко многим через промежуточную таблицу соединений. Теперь мне нужно добавить дополнительные ссылки на свойства, которые принадлежат к паре существующих объектов. У меня есть фиксированное количество этих свойств для каждой пары, хотя одна запись в таблице свойств может применяться к нескольким парам (или даже использоваться несколько раз для одной пары). Я пытаюсь определить лучший способ сделать это, и мне трудно разобраться, как думать о ситуации. С семантической точки зрения кажется, что я могу описать это как любое из следующего с одинаковой точностью:
- Одна пара связана с одним набором фиксированного числа дополнительных свойств
- Одна пара связана со многими дополнительными свойствами
- Многие (два) объекта связаны с одним набором свойств
- Многие объекты связаны со многими свойствами
пример
У меня есть два типа объекта, х и у, каждый с уникальными идентификаторами, и связывающую таблицу objx_objy
с колоннами x_id
и y_id
, которые вместе образуют первичный ключ для ссылки. Каждый X может быть связан со многими Ys, и наоборот. Это установка для моих существующих отношений «многие ко многим».
Базовый вариант
Теперь дополнительно у меня есть набор свойств, определенных в другой таблице, и набор условий, при которых данная пара (X, Y) должна иметь свойство P. Число условий является фиксированным и одинаковым для всех пар. Они в основном говорят: «В ситуации C1 пара (X1, Y1) имеет свойство P1», «В ситуации C2 пара (X1, Y1) имеет свойство P2» и т. Д. Для трех ситуаций / условий для каждой пары в соединении стол.
Опция 1
В моей нынешней ситуации есть ровно три такие условия, и у меня нет никаких оснований ожидать , что для увеличения, поэтому одна возможность заключается в том, чтобы добавить столбцы c1_p_id
, c2_p_id
и c3_p_id
к featx_featy
, указав для данного x_id
и y_id
, что свойство p_id
для использования в каждом из трех случаев ,
Это не кажется мне хорошей идеей, потому что это усложняет SQL для выбора всех свойств, применяемых к объекту, и не может легко масштабироваться для большего количества условий. Тем не менее, он обеспечивает выполнение определенного количества условий для каждой пары (X, Y). Фактически, это единственный вариант, который делает это.
Вариант 2
Создайте таблицу условий cond
и добавьте идентификатор условия в первичный ключ таблицы соединений.
Одним из недостатков этого является то, что он не определяет количество условий для каждой пары. Другое дело, что, когда я рассматриваю только начальные отношения, с чем-то вроде
SELECT objx.*, objy.* FROM objx
INNER JOIN objx_objy ON objx_objy.x_id = objx.id
INNER JOIN objy ON objy.id = objx_objy.y_id
Затем я должен добавить DISTINCT
пункт, чтобы избежать повторяющихся записей. Кажется, это утратило тот факт, что каждая пара должна существовать только один раз.
Вариант 3
Создайте новый «идентификатор пары» в соединительной таблице, а затем добавьте вторую таблицу ссылок между первой и свойствами и условиями.
Кажется, это имеет наименьшее количество недостатков, кроме отсутствия принудительного применения фиксированного количества условий для каждой пары. Имеет ли смысл создавать новый идентификатор, который не идентифицирует ничего, кроме существующих идентификаторов?
Вариант 4 (3б)
В основном так же, как вариант 3, но без создания дополнительного поля идентификатора. Это достигается путем помещения обоих исходных идентификаторов в новую таблицу соединений, чтобы она содержала x_id
и y_id
поля, а не xy_id
.
Дополнительным преимуществом этой формы является то, что она не изменяет существующие таблицы (хотя они еще не работают). Тем не менее, он в основном дублирует всю таблицу несколько раз (или чувствует себя так, во всяком случае), поэтому также не кажется идеальным.
Резюме
Я чувствую, что варианты 3 и 4 достаточно похожи, чтобы я мог пойти с любым из них. Я бы, наверное, уже имел, если бы не требовалось небольшое фиксированное количество ссылок на свойства, что делает Вариант 1 более разумным, чем в противном случае. Основываясь на некотором очень ограниченном тестировании, добавление DISTINCT
предложения в мои запросы, похоже, не влияет на производительность в этой ситуации, но я не уверен, что вариант 2 представляет ситуацию так же, как и другие, из-за собственного дублирования, вызванного размещением одинаковые (X, Y) пары в нескольких строках таблицы ссылок.
Является ли один из этих вариантов моим лучшим способом продвижения вперед, или я должен рассмотреть другую структуру?
источник
DISTINCT
статьи, я думал о запросе , как один в конце # 2, ссылкаx
иy
через ,xyc
но не относится кc
... Так что, если я(x_id, y_id, c_id)
ограниченUNIQUE
рядам(1,1,1)
и(1,1,2)
, затемSELECT x.id, y.id FROM x JOIN xyc JOIN y
, я вернусь два идентичных строки(1,1)
, и(1,1)
.Ответы:
Опция 1
Это не обязательно усложняет запрос SQL (см. Заключение ниже).
Он легко масштабируется до большего количества условий, пока существует фиксированное количество условий, а их нет десятков или сотен.
Это так, и хотя в комментарии вы говорите, что это «наименее важное из моих требований», вы еще не сказали, что это не имеет значения.
Вариант 2Я думаю, что вы можете отклонить эту опцию из-за упомянутых вами осложнений.
objx_objy
Таблица, вероятно, будет движущей стол для некоторых из ваших запросов (например , «выбрать все свойства , примененные к функции», которые я принимаю в виду все свойства , примененные кobjx
илиobjy
). Вы можете использовать представление для предварительного применения,DISTINCT
поэтому не нужно усложнять запросы, но это приведет к очень плохому увеличению производительности при очень небольшом выигрыше.Вариант 3Нет, это не так - Вариант 4 лучше во всех отношениях.
Вариант 4
Эта опция хороша - это очевидный способ установить отношения, если число свойств является переменным или может быть изменено
Вывод
Я предпочел бы вариант 1, если число свойств в
objx_objy
одном, вероятно, будет стабильным, и если вы не можете себе представить, добавив больше, чем несколько дополнительных. Это также единственная опция, которая применяет ограничение «количество свойств = 3» - применение аналогичного ограничения для опции 4, вероятно, будет включать добавлениеc1_p_id
… столбцов в таблицу xy в любом случае *.Если вы действительно не сильно заботитесь об этом условии, и у вас также есть основания сомневаться в том, что число свойств будет стабильным, выберите вариант 4.
Если вы не уверены, какой именно, выберите вариант 1 - он проще, и это определенно лучше, если у вас есть этот вариант, как говорили другие. Если вы отменили опцию 1 «… потому что это усложняет SQL для выбора всех свойств, применяемых к объекту…», я предлагаю создать представление, чтобы предоставить те же данные, что и в дополнительной таблице в варианте 4:
Вариант 1 таблицы:
посмотреть, чтобы "подражать" вариант 4:
«выбрать все свойства, примененные к объекту»:
dbfiddle здесь
источник
Я полагаю, что любой из этих вариантов может сработать, но я бы выбрал вариант 1, если число условий действительно установлено на 3, и вариант 2, если это не так. Бритва Оккама также работает для проектирования баз данных, при прочих равных условиях самый простой дизайн обычно является лучшим.
Хотя, если вы хотите следовать строгим правилам нормализации базы данных, я считаю, что вам нужно использовать 2 независимо от того, фиксировано ли количество условий.
источник