Чому я не повинен мати одну таблицю для кількох стосунків?


12

Якщо припустити, що у моїй базі даних є декілька відносин, наприклад, Магазин, Співробітник та Продаж, і я хочу з'єднати пари з простими бінарними відносинами. Особисто я створив таблиці на ім'я 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, але гірше, тому що він поширює стовпці, а не рядки!
onedaywhen

Відповіді:


13

Що пропонує ваш колега в якості основного ключа для цієї таблиці посилань?
Стовпці первинного ключа звичайно не можуть бути NULL: таблиця вище має нульовий характер.

У наведеному вище прикладі не існує жодного природного ідентифікатора рядків (що таке ПК) (стовпець IDENTITY не є первинним ключем), тому він не працює в будь-якому процесі моделювання. Навіть не думайте про створення таблиць без якоїсь моделі (ERD, ORM, IDEF1X, будь-яка інша)

Вам також знадобляться ПЕРЕВІРИТИ обмеження, щоб переконатися, що у вас немає тристоронніх посилань.

Нарешті, ви ухиляєтесь від 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 Також ваш колега повинен показати нам авторитетну статтю, яка демонструє цю методику. Я свого часу бачив цілі груди сміття, але не повторюю їх ...
gbn

12

Перша практична причина, яку я можу придумати, - це продуктивність.

У "традиційній" моделі ви можете мати унікальний індекс на Idemployee, Idstoreбудь-яких полях та будь-які результати, а також отримувати велику ефективність при пошуку. Його також легко підтримувати для вставок. Унікальні індекси дозволяють вам частіше зливати об’єднання, що може зробити безліч JOINшвидко.

У вашій прикладі моделі, щоб отримати гідну продуктивність, вам потрібно мати один індекс поля на кожному полі ФК у таблиці як мінімум, в ідеалі - індекс покриття для всіх комбінацій, на які буде посилатися, тобто:

  • Співробітник / магазин
  • Співробітник / продаж

Я не впевнений, що таке linktype, але якщо ви посилаєтесь на нього, він, ймовірно, повинен бути індексований.

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

Це також ускладнить вашу логіку. Вам потрібно буде зробити пошук у службовому номері, знайти рядок із порожнім значенням магазину та оновити; або просто вставте новий рядок для кожного нового посилання, яке вражає мету консолідації полів.

В основному ви будете використовувати БІЛЬШ дисковий простір, маючи БІЛЬШЕ індекси для підтримки, і ускладнюєте свою логіку практично без причин. Єдина «користь» - це менша кількість таблиць, з якою потрібно працювати.


Стовпець LinkType є чимось дискримінатором. Просто розповідаємо, до якої пари насправді відноситься ряд. Просто додає до контрацепції, якщо ви запитаєте мене.
Томаш Плюскевич

@TomaszPluskiewicz Я думаю, що найкращим способом показати йому, чому це смокче, - це створити зразок набору даних із обома видами таблиць у ньому та запустити деякі запити. Його модель буде набагато повільніше, ніж традиційна модель
JNK

4

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

Це необхідно, якщо типи відносин визначені користувачем під час виконання. Однак це дуже рідко так.

У вашому прикладі відносини не поділяють атрибутів, а стосунки навіть посилаються на дві різні таблиці. Це ускладнює виконання обмежень, а дизайн також менш інтуїтивний.

Я вибрав би такий дизайн, лише якщо створення таблиць буквально коштує грошей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.