Це погана практика мати кілька взаємовиключних взаємовідносин один на один?


38

Скажімо, таблиця carмає один-до-одного відношення до таблиць electric_car, gas_carі hybrid_car. Якщо a carє electric_car, воно більше не може з'являтися в gas_cara або hybrid_carтощо.

Чи щось не так з таким дизайном? Якісь проблеми, які можуть виникнути в дорозі?

Відповіді:


59

Різні типи автомобілів є прикладом загальної проблеми, яка виникає знову і знову при моделюванні даних. Це називається "узагальнення / спеціалізація" в моделюванні ER, а "надклас / підклас" в об'єктному моделюванні.

Об'єктний моделер використовує функції успадкування, вбудовані в об'єктну модель, для вирішення проблеми досить легко. Підкласи просто розширюють надклас.

Реляційний моделер стикається з проблемою. як розробити таблиці так, щоб наслідувати переваги, які отримали б від спадщини?

Найпростіша техніка називається успадкуванням однієї таблиці . Дані про всі типи автомобілів згруповані в єдину таблицю для автомобілів. Є колонка, тип car_type, яка об'єднує всі машини одного типу. Жоден автомобіль не може належати до більш ніж одного типу. Якщо стовпець не має значення для, скажімо, електромобілів, він буде залишений NULL у рядках, що стосуються електромобілів.

Це просте рішення добре працює для менших і простих випадків. Наявність великої кількості NULL додає крихітний біт для накладних витрат, а трохи - для накладних витрат. Розробнику, можливо, доведеться вивчити тризначну логіку SQL, якщо булеві тести виконуються на нульових стовпцях. Спочатку це може бути неприємно, але людина звикає.

Існує ще одна методика, яка називається успадкуванням таблиці класів . У цій конструкції є окремі таблиці для автомобіля gas_car, electric_car та hybrid_car, крім комбінованого столу, автомобіля для всіх них. Коли ви хочете отримати всі дані про конкретний вид автомобіля, ви приєднуєте автомобільний стіл до відповідної спеціалізованої таблиці. У цій конструкції менше NULL, але ви робите більше приєднання. Ця техніка краще працює у великих та складніших випадках.

Існує третя техніка, яка називається спільним первинним ключем. Цей прийом часто використовується в поєднанні з успадкуванням таблиці класів. Спеціалізовані таблиці для підкласів в якості основного ключа мають копію первинного ключа відповідного запису в таблиці автомобілів. Цей стовпець id може бути оголошений як первинним, так і зовнішнім ключем.

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

Суперкласи та підкласи трапляються постійно в реальному світі. Не бійтеся. Але протестуйте свій початковий дизайн на ефективність. Якщо ваша перша спроба проста і слушна, ви зможете налаштувати її, щоб пришвидшити її.


3
Дякую вам! Це місце на тому, що я намагався з'ясувати. Схоже, успадкування таблиці класів саме те, що мені потрібно. Я змінив свою прийняту відповідь на це для майбутніх читачів, оскільки думаю, що це повністю охоплює це питання, а не лише мій випадок.
Артур Тарасов

6
Відмінна відповідь тут. Одна порада: ретельно документуйте ці дизайнерські рішення. Який би шлях ви не взяли, це буде не очевидно, коли хтось вивчить структуру бази даних. Деякі бази даних, такі як Postgres, дозволяють зв’язати коментар разом із метаданими ваших стовпців, таблиць тощо.
Василь Бурк

Ви не звертаєтесь до обмеження щодо того, щоб електромобілі не були також гібридними. Для цього вам потрібна окрема таблиця.
jmoreno

2
Ти правий. Якщо ви додасте поле car_type до таблиці автомобілів, ви можете обмежити приналежність автомобілів лише до одного типу за рахунок відхилення від повної нормалізації. Хороша СУБД дозволить вам визначити обмеження чека, яке не дозволить автомобілю потрапити в більш ніж одну спеціалізовану таблицю. У цьому є деякі накладні витрати, ви їдете додавати нові машини.
Вальтер Мітті

@WalterMitty, але без car_typeполя, як би ви дізналися, у якій таблиці шукати деталі під час отримання даних? Чи потрібно вам прочитати всі три таблиці, щоб побачити, яка з них має дані про конкретний carзапис?
Джош Частина

12

Немає нічого поганого в тому, що у вашій моделі є стільки субтитрів сутності, скільки потрібно для відображення реальності даних, які ви намагаєтеся моделювати. Питання не в тому, чи є підтипи поганою практикою. Проблема може полягати в тому, що це хороша модель ?

Наприклад, під вашим прикладом, що ви робите з чимось на кшталт Audi A4 eTron - це гібрид плагіну? Це "електромобіль" чи це "гібридна машина"?

Інше питання, яке ви повинні задати собі, це чому ви взагалі підміняєте текст? Скільки чітких предикатів у ваших підтипах? Чи поділяється будь-який із цих предикатів між підтипами? Ситуація може ускладнитися.

Підтипизація не використовується в дизайні баз даних для класифікації. Можна класифікувати за допомогою кодів, зовнішніх ключів до кодових таблиць або з прапорами. Субтекст використовується для моделювання різних наборів предикатів для різних типів цікавої речі. Якщо ви використовуєте підтипи лише для класифікації, це погана практика.

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


Дякую, я боявся, що я встановлюю собі якусь пастку. Моя проблема полягає в тому, що кожен з підтипів матиме багато стовпців. Деякі будуть перетинатися, і я покладу їх у carтаблицю, але багато хто не буде і буде розміщено в таблиці підтипу. Наприклад, це буде щось на зразок зберігання елементарних частин типів автомобілів. Електродвигун автомобіля може мати як 100 деталей, газовий автомобільний двигун на 75 частин, так і гібридний 125 частин. 50 частин будуть загальними і зберігатися в cars, в той час як 50, 25 і 75 буде electric_car, gas_carі hybrid_carстоли
Артур Тараси
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.