Почему у меня не должно быть одной таблицы для нескольких отношений?

12

Предполагая, что у меня есть несколько отношений в моей базе данных, например, Store, Employee и Sale, и я хочу соединить пары с помощью простого бинарного отношения. Лично я бы создал таблицы с именами Employee_Store и Employee_Sale с естественным ключом, состоящим из внешних ключей.

Теперь мой коллега настаивает на создании одной таблицы для нескольких отношений. Для приведенного выше примера может быть таблица с именем EmployeeLinks:

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

Пожалуйста, помогите мне с вескими причинами, почему это не очень хорошая идея. У меня есть свои аргументы, но я хотел бы сохранить их в тайне и выслушать ваши объективные мнения.

РЕДАКТИРОВАТЬ:

Первоначально в таблице выше не было бы первичного ключа (!). Поскольку внешние ключи допускают нулевое значение, суррогатный ключ является единственным вариантом.

Томаш Плюскевич
источник
3
Это как OTLT или EAV, но хуже, потому что он увеличивает количество столбцов, а не строк!
понедельник,

Ответы:

13

Что ваш коллега предлагает в качестве первичного ключа для этой таблицы ссылок?
Конечно, столбцы первичного ключа не могут иметь значение NULL: таблица выше имеет значение NULL.

В приведенном выше примере нет естественного идентификатора строки (которым является PK) (столбец IDENTITY не является первичным ключом), поэтому он завершается неудачно в любом процессе моделирования. Даже не думайте о создании таблиц без какой-либо модели (ERD, ORM, IDEF1X и т. Д.)

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

Наконец, вы отклоняетесь от 4-й и 5-й территории нормальной формы, но по неправильным причинам.

Я не могу найти никаких примеров в Интернете: это показывает, насколько это глупо

ГБН
источник
4
+1 заI can't find any examples on the internet: that shows how stupid this is
JNK
Я прояснил вопрос о первичном ключе. Кроме того, по-видимому, мой коллега действительно сталкивался с таким дизайном раньше или мне так сказали
Томаш Плюскевич
@Tomasz Pluskiewicz: суррогатный ключ не является первичным ключом! Он выбран для дополнения естественного ключа во время реализации. См. Dba.stackexchange.com/a/13779/630 Кроме того, ваш коллега должен показать нам авторитетную статью, которая демонстрирует эту технику. Я видел
целые
12

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

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

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

  • Сотрудник / магазин
  • Сотрудник / Продажа

Я не уверен, что такое linktype, но если вы ссылаетесь на него, он, вероятно, должен быть проиндексирован.

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

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

В основном вы будете использовать БОЛЬШЕ дискового пространства, иметь БОЛЬШЕ индексов для обслуживания и усложнять свою логику по существу без причины. Единственное «преимущество» - это меньшее количество таблиц, с которыми нужно иметь дело.

JNK
источник
Столбец LinkType является чем-то вроде дискриминатора. Просто сказать, какая пара на самом деле относится к ряду. Просто добавляет к хитрости, если вы спросите меня.
Томаш Плюскевич
@ TomaszPluskiewicz Я думаю, что лучший способ показать ему, почему это отстой, - это создать образец набора данных с обоими типами таблиц в нем и выполнить несколько запросов. Его модель будет намного медленнее, чем традиционная модель
JNK
4

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

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

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

Я бы выбрал этот дизайн, только если создание таблиц буквально стоит денег.

JMD Coalesce
источник