Проектирование баз данных - одна таблица ссылок или несколько таблиц ссылок? - PullRequest
0 голосов
/ 10 мая 2010

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

Я не администратор БД, просто несколько базовых курсов БД. Как я понимаю, типичным решением в этом случае было бы объединение нескольких таблиц ссылок для соединения с каждой «реальной» таблицей. Вот что я предлагаю вместо этого: одна таблица ссылок, которая имеет зависимости внешнего ключа от всех других PK других таблиц.

Есть ли причина, по которой это может плохо с точки зрения масштабируемости, гибкости и т. Д. В будущем?

Ответы [ 4 ]

1 голос
/ 10 мая 2010

Если я правильно понимаю ваше предложение, то, о чем вы думаете, это незначительное изменение в «Единой истинной таблице поиска» (OTLT), что не является хорошей идеей. В этом случае, возможно, OTLT расшифровывается как «One True Linking Table».

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

ReferencingTable     INTEGER (or VARCHAR(xx)?)
ReferencingId        INTEGER
ReferencedTable      INTEGER (or VARCHAR(xx)?)
ReferencedId         INTEGER

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

Далее вам нужно беспокоиться об асимметрии в именовании столбцов в том, что должно быть симметричным; OTLT соединяет Таблицу1 с Таблицей2 так же, как соединяет Таблицу2 с Таблицей1 - если только ваши отношения не являются асимметричными. Это просто чрезвычайно усложняет жизнь.

Теперь предположим, что вам нужно соединить первичные таблицы от Table1 до Table2 и от Table2 до Table3, каждая через OTLT, и что идентификаторы таблицы равны 1, 2 и 3, и что ReferencingTable всегда меньше два в OTLT:

SELECT T1.*, T2.*, T3.*
  FROM Table1 AS T1
  JOIN OTLT   AS O1 ON T1.Id = O1.ReferencingId AND O1.ReferencingTable = 1
  JOIN Table2 AS T2 ON T2.Id = O1.ReferencedId  AND O1.ReferencedTable  = 2
  JOIN OTLT   AS O2 ON T2.Id = O2.ReferencingId AND O2.ReferencingTable = 2
  JOIN Table3 AS T3 ON T3.Id = O2.ReferencedId  AND O2.ReferencedTable  = 3

Итак, у вас есть два независимых набора соединений через OTLT.

Альтернативная формулировка использует отдельные соединительные таблицы для каждой пары. Строки в этих соединяющих таблицах меньше:

ReferencingID    INTEGER
ReferencedID     INTEGER

И, предполагая, что объединяющие таблицы называются Join_T1_T2 и т. Д., Запрос выше становится:

SELECT T1.*, T2.*, T3.*
  FROM Table1     AS T1
  JOIN Join_T1_T2 AS J1 ON T1.Id = J1.ReferencingId
  JOIN Table2     AS T2 ON T2.Id = J1.ReferencedId
  JOIN Join_T2_T3 AS J2 ON T2.Id = J2.ReferencingId
  JOIN Table3     AS T3 ON T3.Id = J2.ReferencedId

Существует столько же ссылок на таблицы (5), сколько и раньше, но СУБД может автоматически поддерживать ссылочную целостность в этих соединяемых таблицах - тогда как обслуживание должно быть написано вручную с помощью OTLT. Объединения проще (без предложений AND).

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

0 голосов
/ 10 мая 2010

У вас есть два варианта с этой настройкой.

  • Убедитесь, что в каждой строке указана ссылка только на одну таблицу. Это вырожденная модель наличия отдельных таблиц соединения.
  • Убедитесь, что у вас есть все комбинации ссылок, которые сильно увеличивают размер таблицы. Учитывая строку в первичной таблице, которая соединяется с 4, 5 и 6 записями в каждой из трех других таблиц, вам нужно 4 * 5 * 6 = 120 строк в вашей таблице соединения. Вам также нужна логика, чтобы не обрабатывать соединения с таблицей. Если вам нужно присоединиться только к первым таблицам, вам нужно отфильтровать 120 строк, которые вы сократили до 4.

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

0 голосов
/ 10 мая 2010

Моя главная проблема с одной таблицей ссылок, если «ссылка» внезапно превратилась в сущность. Например, у вас могут быть объекты «покупатель» и «магазин». это может быть много ко многим, так как покупатель может пойти во многие магазины, и в магазине будет много покупателей.

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

0 голосов
/ 10 мая 2010

То есть вы пытаетесь решить, взять ли звездочку или звездочку?

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

Main   Junct  Total
-------------------
   2       1      3
   3       3      6
   4       6     10
   5      10     15
   6      15     21
   7      21     28!

7, вероятно, самое большее, что вы бы имели в схеме базы данных.Таким образом, вы можете выполнять сложные запросы, включающие 3 основные таблицы, без необходимости проходить через 3 соединительные таблицы, а просто касаться только одной соединительной таблицы, независимо от того, сколько основных таблиц вы хотите.Нет. Гибкость?Только если ваша схема кардинально меняется.

...