Коли мені слід використовувати один до одного стосунки?


91

Вибачте за це запитання про нуб, але чи є реальні потреби використовувати взаємозв'язок "один на один" з таблицями у вашій базі даних? Ви можете реалізувати всі необхідні поля всередині однієї таблиці. Навіть якщо дані стають дуже великими, SELECTзамість використання ви можете перерахувати імена стовпців, які вам потрібні SELECT *. Коли вам справді потрібна ця розлука?

Відповіді:


104

Від 1 до 0..1

  • "1 до 0..1" між супер-та підкласами використовується як частина стратегії "всі класи в окремих таблицях" для реалізації успадкування .

  • "1 до 0..1" може бути представлений в одній таблиці з частиною "0..1", що охоплюється полями, що підтримують NULL. Однак, якщо відношення переважно "1 до 0" із лише декількома рядками "1 до 1", розбиття частини "0..1" на окрему таблицю може заощадити деякі переваги зберігання (та продуктивності кешу). Деякі бази даних вигідніше зберігати NULL, ніж інші, тому "граничний пункт", коли ця стратегія стає життєздатною, може значно відрізнятися.

1 до 1

  • Справжній "1 до 1" вертикально розділяє дані, що може мати значення для кешування. Бази даних зазвичай реалізують кеш-пам’яті на рівні сторінки, а не на рівні окремих полів, тому навіть якщо ви вибрали лише кілька полів із рядка, зазвичай кешується вся сторінка, якій належить рядок. Якщо рядок дуже широкий, а вибрані поля відносно вузькі, ви в кінцевому підсумку кешуєте багато інформації, яка вам насправді не потрібна. У такій ситуації може бути корисним вертикально розділити дані, тому кешована лише вужча, часто використовувана частина або рядки, тому більша їх кількість може поміститися в кеш, роблячи кеш фактично «більшим».

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

  • Тригери також, як правило, специфічні для таблиці. Хоча теоретично ви можете мати лише одну таблицю, а тригер ігноруватиме «неправильну половину» рядка, деякі бази даних можуть накласти додаткові обмеження на те, що може, а що не може тригер, що може зробити це недоцільним. Наприклад, Oracle не дозволяє вам змінювати мутуючу таблицю - маючи окремі таблиці, лише одна з них може мутувати, тому ви все одно можете змінити іншу зі свого тригера.

  • Окремі таблиці можуть забезпечити більш детальний захист.

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


20

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

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


19

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

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

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

У таких випадках не годиться мати все в одній таблиці. Крім того, нелегко мати справу з таблицею, яка має 45 стовпців!


17

Мої 2 центи.

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

create table users ( id int primary key, ...);
create table users_fbdata ( id int primary key, ..., constraint users foreighn key ...)
create table users_twdata ( id int primary key, ..., constraint users foreighn key ...)

13

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

Інша причина полягає в тому, що ви хочете спеціалізувати концепцію по-різному. Якщо у вас є таблиця Person і ви хочете додати концепцію різних типів Person, таких як працівник, клієнт, акціонер - кожному з них потрібні різні набори даних. Дані, подібні між ними, будуть у таблиці Особи, інформація про спеціаліста - у конкретних таблицях для Клієнта, Акціонера, Співробітника.

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

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


5

не дуже часто.

Ви можете знайти певну вигоду, якщо вам потрібно застосувати певний захист - тому деякі користувачі можуть бачити деякі стовпці (таблиця1), але не інші (таблиця2) ..

Звичайно, деякі бази даних (Oracle) дозволяють робити такий тип захисту в одній таблиці, а деякі інші - ні.


5

Ви маєте на увазі нормалізацію бази даних. Одним із прикладів, про який я можу подумати в програмі, яку я підтримую, є елементи. Додаток дозволяє користувачеві продавати багато різних типів предметів (тобто InventoryItems, NonInventoryItems, ServiceItems тощо ...). Хоча я міг зберігати всі поля, необхідні для кожного елемента, в одній таблиці елементів, набагато простіше підтримувати наявність базової таблиці елементів, яка містить поля, загальні для всіх елементів, а потім окремі таблиці для кожного типу елементів (тобто Інвентар, Неінвентар, тощо), які містять поля, характерні лише для цього типу товару. Тоді таблиця елементів матиме зовнішній ключ до певного типу елемента, який вона представляє. Взаємозв'язок між таблицями конкретних елементів та таблицею базових елементів буде індивідуальним.

Нижче - стаття про нормалізацію.

http://support.microsoft.com/kb/283878


3

Як і на всі питання дизайну, відповідь "це залежить".

Є кілька міркувань:

  • наскільки великою стане таблиця (як з точки зору полів, так і рядків)? Це може бути незручно зберігати ім’я та пароль ваших користувачів з іншими менш часто використовуваними даними як з точки зору обслуговування, так і з точки зору програмування

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

  • наскільки ви впевнені, що стосунки будуть 1: 1? Як зазначає це запитання, все може швидко ускладнитися.


3

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


2

Зазвичай я стикаюся з двома загальними типами відносин 1: 1 на практиці:

  1. Відносини IS-A, також відомі як відносини супертипу / підтипу. Це коли один вид сутності насправді є типом іншого (EntityA IS A EntityB). Приклади:

    • Фізична особа, з окремими фірмами для бухгалтера, інженера, продавця, у межах однієї компанії.
    • Сутність елемента з окремими сутностями для Widget, RawMaterial, FinishedGood тощо.
    • Автомобільний об’єкт, з окремими об’єктами для вантажівок, седанів тощо.

    У всіх цих ситуаціях об'єкт супертипу (наприклад, Особа, Предмет чи Автомобіль) мав би атрибути, загальні для всіх підтипів, а сутності підтипів мали б атрибути, унікальні для кожного підтипу. Первинний ключ підтипу буде таким самим, як і ключ супертипу.

  2. Відносини "начальника". Це коли людина є унікальним начальником або керівником або керівником організаційного підрозділу (відділу, компанії тощо). Якщо для організаційного підрозділу дозволено лише одного начальника, то між особою, яка представляє начальника, та організаційною одиницею існує співвідношення 1: 1.


1
Мені подобається другий приклад. Ви можете мати організацію "Відділ" та організацію "Співробітник". В одному відділі у вас багато співробітників, і працівник може працювати лише в одному відділі. Це 1: n. Працівник може бути керівником відділу - лише одного підрозділу, а підрозділ має лише одного керівника. Отож ви отримуєте дві таблиці, пов’язані двома співвідношеннями - 1: n та 1: 1.
cezar

2

По-перше, я думаю, це питання моделювання та визначення того, що складається з окремої сутності. Припустимо, у вас customersодин і тільки один сингл address. Звичайно, ви можете реалізувати все в одній таблиціcustomer , але якщо в майбутньому ви дозволите йому мати 2 або більше адрес, то вам потрібно буде це переформатувати (не проблема, але прийміть свідоме рішення).

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

Уявіть, знову ж таки, у вас є customersпо одному address, але цього разу необов’язково мати адресу. Звичайно, ви можете реалізувати це як купу NULL-able стовпців, таких як ZIP,state,street. Але припустимо, що з огляду на те, що у вас є адреса, стан не є обов’язковим, але ZIP є. Як змоделювати це в одній таблиці? Ви можете використовувати обмеження для customerтаблиці, але набагато простіше розділити в іншій таблиці і зробити чужий_ключ NULLable. Таким чином ваша модель набагато чіткіше говорить, що сутність address є необов’язковою, а що ZIPє необов’язковим атрибутом цієї сутності.


0

Під час програмування я стикався з цим лише в одній ситуації. Це тоді, коли між тими самими 2 сутностями («Суб’єкт А» та «Суб’єкт В») існує взаємозв’язок «1 до багатьох» та «1 до 1».

Коли "Суб'єкт А" має декілька "Суб'єкт В", а "Суб'єкт В" має лише 1 "Суб'єкт А", а "Суб'єкт А" має лише 1 поточний "Суб'єкт В", а "Суб'єкт Б" має лише 1 "Суб'єкт А".

Наприклад, у автомобіля може бути лише один поточний водій, а водій може їздити лише по одному автомобілю за раз - тому співвідношення між поняттями автомобіля та водія буде 1 до 1. - Я запозичив цей приклад у відповіді @Steve Fenton

Де водій може керувати кількома автомобілями, тільки не одночасно. Отже, сутності автомобіля та водія - 1-до-багатьох або багато-до-багатьох. Але якщо нам потрібно знати, хто є поточним драйвером, то нам також потрібне відношення 1 до 1.


0

Іншим варіантом використання може бути перевищення максимальної кількості стовпців у таблиці бази даних. Тоді ви можете приєднатися до іншої таблиці за допомогою OneToOne

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