Що не так із іноземними ключами?


259

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

У людей є якісь вагомі причини того, щоб (щоб уникнути дискусії відповідно до принципів переповнення стека)?

Редагувати: "У мене ще немає причин створити зовнішній ключ, тому це може бути моєю першою причиною фактично створити його".


9
Я не думаю, що Джоел не використовує ФК, це просто те, що він не змушує їх базу даних застосовувати. Логічно, вони все-таки ФК!
Дарен Томас,

6
Він каже, що не використовує іноземні ключі, але я погоджуюся з Дареном, що він має на увазі, що він не використовує іноземний ключ КОНСТРЕЙНТИ. Стовпчик в одній таблиці, значення якого слід взяти з первинного / унікального ключа іншої таблиці, є зовнішніми ключами, додаєте ви обмеження чи ні.
Тоні Ендрюс

22
... Як правило, нерозумно не додавати обмежень: воно ЗАБЕЗПЕЧАЄ цілісність постійно, навіть якщо в коді програми є помилка або якщо ваша робота працює за кадром, роблячи дані "виправлення".
Тоні Ендрюс

2
+1 Для коментаря Тоні. Існує занадто велика плутанина між функцією та логічною концепцією зовнішніх ключів там.
JohnFx

4
@DanMan, не знаю, де ви створили враження. Я думаю, що це. Я фактично кажу вище "Взагалі нерозумно не додавати обмежень: це ЗАБЕЗПЕЧАЄ цілісність у всі часи"
Тоні Ендрюс

Відповіді:


352

Причини використання іноземних ключів:

  • Ви не отримаєте осиротілих рядів
  • Ви можете отримати приємну поведінку "при видаленні каскаду", автоматично прибираючи таблиці
  • знання про взаємозв'язки між таблицями в базі даних допомагає оптимізатору планувати ваші запити для найбільш ефективного виконання, оскільки він може отримати кращі оцінки щодо простоти приєднання.
  • ФК дають досить великий натяк на те, яку статистику найважливіше збирати в базі даних, що, в свою чергу, призводить до кращої продуктивності
  • вони дозволяють підтримувати всі види автоматичної підтримки - ORM можуть генерувати себе, засоби візуалізації зможуть створити приємні схеми для вас тощо.
  • хтось новий у проекті швидше потрапить у потік речей, оскільки в іншому випадку неявні стосунки явно задокументовані

Причини не використовувати іноземні ключі:

  • ви змушуєте DB працювати додатково на кожній операції CRUD, оскільки він повинен перевіряти послідовність FK. Це може бути великою вартістю, якщо у вас багато кашлю
  • примусово застосовуючи відносини, ФК визначають порядок, у якому ви повинні додавати / видаляти речі, що може призвести до відмови БД робити те, що ви хочете. (Зрозуміло, у таких випадках те, що ти намагаєшся, - це створити Орфа-сиріт, і це зазвичай не є хорошою справою). Це особливо болісно, ​​коли ви робите великі оновлення пакетів, і ви завантажуєте одну таблицю перед іншою, при цьому друга таблиця створює послідовний стан (але якщо ви робите подібне, якщо є можливість, що друге навантаження вийде з ладу і ваш тепер база даних не відповідає?).
  • іноді ви заздалегідь знаєте, що ваші дані будуть забруднені, ви приймаєте це, і ви хочете, щоб БД їх прийняло
  • ви просто ледачі :-)

Я думаю (я не впевнений!), Що більшість створених баз даних надають спосіб вказати зовнішній ключ, який не виконується, і є просто трохи метаданими. Оскільки невиконання викорінює будь-які причини, щоб не використовувати FK, ви, ймовірно, повинні піти цим маршрутом, якщо стосується будь-якої з причин у другому розділі.


12
Гарний список! СУБД не перевірятиме узгодженість для "R" частини CRUD, тому я б це взяв. Крім того, це, мабуть, помилка, оскільки у вашій програмі ви робите те саме, що робить і СУБД: ви перевірите і переконайтеся, що батьківський ідентифікатор дійсний перед CRD, і це насправді повільніше, ніж це робити DBM!
Метт Рогіш

6
Що робити, якщо хтось видаляє батьків, коли ви вставляєте дітей? Прямо зараз, коли я надсилаю "додати коментар" - якщо ви вже видалили свою відповідь, цей коментар зараз є сиротою. ФК би запобігли це. Крім того, я міг просто змінити батьківський номер, щоб він був усім, що я хочу. Хтось повинен перевірити. :)
Метт Рогіш

7
Точно - це повинно бути завданням БД, оскільки це єдине, що може гарантувати транзакцій в умовах багатьох одночасних клієнтів.
SquareCog

3
+1 Відмінна відповідь - другу причину не використовувати обмеження FK можна думати про "важче порушити послідовність", що насправді звучить як гарна річ!
Білл Карвін

9
Переваги використання зовнішніх ключів FAR переважає будь-які переваги від їх використання на мою думку.
Нік Бедфорд

80

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

Якщо ви не мали такого ґрунтовного чи позитивного досвіду у своєму минулому із зусиллями, пов’язаними з RDBMS, ви, ймовірно, не зазнавали такої інформації. Або, можливо, ваше минуле включає занурення в середовище, яке було голосно антибазовим (наприклад, "ці DBA - ідіоти - ми мало, ми вибрали декілька слінгерів коду Java / c # врятуємо день"). до прихованих дзюрчань дебюту, які говорять вам про те, що ФК (і обмеження, які вони можуть передбачити) насправді важливі, якби ви просто слухали.

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


61
Я буду використовувати дистильований "іноземні ключі - це як чистити зуби: ідіть вперед, обійтися без цього, але обережно, коли ви посміхнетесь"
Марк Совул

5
Особисто я вважаю, що принципи RDBMS 'набагато простіші і чіткіше визначені, ніж принципи гігієни ротової порожнини
Алі Ганджі

Через 10 років я впевнений, що з моїм сином / дочкою розмовлятимуть по цій базі даних, щоб він / вона не заплутувались і в кінцевому підсумку стали причиною наступної краху стіни на вулиці через проблему з базою даних.
VarunAgw

52

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

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


26
Я дійсно не отримую людей, які не мають ФК у своїй базі даних. Востаннє, коли я працював з тим, хто цього не мав, він сказав "ні, ми це застосовуємо у заявці". За винятком того, що я провів опитування всіх баз даних клієнтів і виявив, що у більшості з них є сироти ...
ErikE

1
Це, як правило, так і є. Я думаю, що ви можете піти від застосування ТОЛЬКО у базі даних (поки ваші користувачі не заперечують винятки з виконання), але мати обоє - це єдиний шлях.
AlexCuse

Все це у стенограмах / відповіді Етвуда "Етвуд: ... виходячи із закордонних ключів, які ви встановили в індексах, вони це з'ясовують ... Спольський: [сміється] Припускаючи, що ви це робите. Етвуд: Ну, припускаючи, що ви правильно налаштуєте свою базу даних ... "
MemeDeveloper

4
База даних не називаються реляційними через відносин між таблицями (КОЖЕН роду база даних має якийсь - то відносин між сутностями!), А тому , що столи самі відносини , в математиці умовах. Дивіться Вікіпедію .
Массіміліано Краус

41

Іноземні ключі є важливими для будь-якої моделі реляційних баз даних.


54
Модель, так. Реалізація, не суттєва, просто, ймовірно, корисна.
dkretz

4
Вибачте, але головна причина, чому розробники додатків ширше не використовують системи управління об’єктними базами даних (відомі також як бази даних NoSQL!), - це через інвестиції в RDBMS. Більшу частину часу база даних (не система управління базами даних) представляє собою об'єктну модель середнього рівня, яка часто включає розподілені кеші. Тут все одно має відбутися каскадування видалень, право власності та синхронізація змін. RDBMS використовується в першу чергу для збереження цієї об'єктної моделі, і, як правило, після кропіткої та практично нікчемної вправи з ОРМ. Моделі відносин більшість часу не потрібні!
Sentinel

2
ні, іноземні ключі не обов'язкові для позначення "реляційних"
Silver Moon

Це насправді не пояснює багато.
Ней

29

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

Існує також той факт, що багатьом системам взагалі потрібно безпосередньо взаємодіяти з базою даних - від інших систем, які щойно читають дані (Crystal Reports), до систем, що вставляють дані (необов'язково використовуючи розроблений нами API; він може бути написаний тьмяний менеджер, який щойно відкрив VBScript і має пароль SA для вікна SQL). Якщо база даних не є такою ідіотською, як це можливо, прощайте базу даних.

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


2
Приємне розуміння. Я б заперечував, що дані є важливими для кожної програми, яка фактично звикає. Єдине, що відрізняється - це наслідки пошкоджених даних. Вони високо оцінюють ваш додаток ...
Jay Godse

20

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


Іноземні ключі ускладнюють автоматичне тестування

Припустимо, ви використовуєте іноземні ключі. Ви пишете автоматизований тест, який говорить: "Коли я оновлюю фінансовий рахунок, він повинен зберігати запис трансакції". У цьому тесті ви стосуєтесь лише двох таблиць: accountsі transactions.

Однак, accountsмає іноземний ключ до contracts, і contractsмає fk to clients, і clientsfk to cities, і citiesмає fk to states.

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

На це є принаймні дві можливі перспективи:

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

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


Тут я зазвичай переходжу на середній шлях: я використовую FK, потім пишу допоміжні методи тестування, які встановлюють БД для підтримки різних сценаріїв тестування, наприклад, допоміжний метод для заселення "міст" і "штатів" для будь-яких тестів що потребують заповнення таблиць.
joelpt

Можливо, вам слід було б використовувати таблиці зв’язків між непов'язаними об'єктами. Або йдіть далі - окремий DBS: розгляньте ситуацію в сервісно-орієнтованій архітектурі або мікросервісі, де кожен елемент (клієнти, рахунки, транзакції) - це різні системи, з різними БД. Між ними немає ФК. У цьому випадку ФК слід використовувати для запобігання осиротілим даним у підтаблицях для кожного типу даних.
JeeBee

3
Є також СУБД, які дозволяють обмеження відкладати так, що вони перевіряються лише при здійсненні всієї транзакції, тому порядок вставки, оновлення, видалення не має значення
a_horse_with_no_name

2
Якщо ви тестуєте оновлення з бізнес-рівня, у вашому середовищі розробки має бути присутній FK. Під час оновлення запису у вас повинні бути значення стовпців, необхідні для успішного оновлення. Інакше IMHO ваш тест недійсний.
KeyOfJ

3
Ваша база даних навіть не повинна брати участь у ваших тестових одиницях, ви повинні з них глузувати. У тестуванні інтеграції вони братимуть участь, але будь-які проблеми, пов’язані із зовнішніми ключами, - це те, що і ваші користувачі будуть стикатися, якщо ви не виправите це.
Andreas Bergström

16

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

Важливо пам’ятати, що стандарт SQL визначає дії, які виконуються під час видалення або оновлення зовнішнього ключа. Я знаю:

  • ON DELETE RESTRICT- Запобігає видаленню будь-яких рядків у іншій таблиці, у яких є ключі в цьому стовпці. Це описав вище Кен Рей.
  • ON DELETE CASCADE - Якщо рядок в іншій таблиці видалено, видаліть рядки з цієї таблиці, на які посилається.
  • ON DELETE SET DEFAULT - Якщо рядок в іншій таблиці видалено, встановіть будь-які сторонні ключі, посилаючись на типовий стовпець.
  • ON DELETE SET NULL - Якщо рядок в іншій таблиці видалено, встановіть будь-які сторонні ключі, що посилаються на неї в цій таблиці, на нуль.
  • ON DELETE NO ACTION- Цей зовнішній ключ лише означає, що це іноземний ключ; а саме для використання в АБО картах.

Ці ж дії стосуються і ON UPDATE.

Здається, за замовчуванням залежить те, що сервер, який ви використовуєте.


14

@imphasing - саме такий тип мислення, який викликає кошмари технічного обслуговування.

Чому о, чому б ви ігнорували декларативну референтну цілісність, де дані можна гарантувати як мінімум узгоджені, на користь так званого "програмного забезпечення", що є в кращому випадку слабким запобіжним заходом.


Тому що залучені розробники ніколи не вирішували проблеми, яка вимагає нетривіальної, нормалізованої реляційної моделі. Багато проблем не виникає, особливо це стосується програмного забезпечення типу "Інтернет" / "соціальні медіа", яке є всім маренням сьогодні. Якщо будь-який вибіг із заднього кінця рамки ORM задовольняє проблему в альфа, навряд чи хтось задумається набагато більше про моделювання даних. Багато таких проблем так само легко вирішуються через магазини K / V, бази даних документів або серіалізацію прямого об'єкта.
zxq9

12

Є одна вагома причина не використовувати їх: якщо ви не розумієте їх ролі або як їх використовувати.

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

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


8
Видалення рядка у виробництві без резервного копіювання не є вагомим аргументом. Якщо ви їх не розумієте, вам варто подумати про це, а не опускати.
Гійом

2
@Guillaume Я думаю, що його відповідь була трохи саркастичною, і це не слід сприймати буквально: якщо ви їх не розумієте, тоді не використовуйте їх. Але звичайно, ви повинні їх розуміти і використовувати.
Бенджамін

^ Це. Вони є корисними інструментами, але в руках початківця - небезпечні інструменти.
Кент Фредрік

11

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


11
Чому сирітські ряди - це велика справа?
Seun Osewa

2
А як щодо багатопотокової роботи? Вони можуть викликати багатопоточний кошмар у певних ситуаціях. У складному додатку з декількома потоками, що записують базу даних, які можуть стикатися з об'єктами, на які потрібно посилатися один на одного, краще контролювати референтну цілісність у бізнес-логіці --- особливо, якщо таблиці згодом стануть статичними.
Кіт Пінсон

Я згоден. Крім того, я вважаю за краще мати ряди офанів, які я можу відновити пізніше, ніж їх нещадно відкидати.
PedroD

4

Питання більш важливе: ви б їздили із зав'язаними очима? Ось так і відбувається, якщо ви розробляєте систему без референтних обмежень. Майте на увазі, що вимоги бізнесу змінюються, змінюється дизайн додатків, відповідні логічні припущення в коді, сама логіка може бути відновлена ​​і так далі. Загалом, обмеження в базах даних встановлюються під сучасними логічними припущеннями, здавалося б, правильними для певного набору логічних тверджень та припущень.

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

До предмету цього переліку - іноземний ключ сам по собі не «покращує ефективність», а також не «погіршує результативність» з точки зору системи обробки транзакцій у режимі реального часу. Однак існує сукупна вартість перевірки обмежень у системі "пакетних" ВИСОКОГО обсягу. Отже, ось різниця в режимі реального часу та пакетних транзакцій; пакетна обробка - там, коли збільшена вартість, отримана за допомогою перевірок обмежень, послідовно обробленої партії є результатом ефективності.

У добре розробленій системі перевірки узгодженості даних здійснювались би "до" обробки пакету (проте, тут також пов'язана вартість); тому перевірки обмежень зовнішнього ключа не потрібні протягом часу завантаження. Насправді всі обмеження, включаючи зовнішній ключ, повинні бути тимчасово відключені до обробки пакету.

ЗАПИТАННЯ ЕКСПЛУАТАЦІЇ - якщо таблиці з'єднані на зовнішніх ключах, майте на увазі той факт, що стовпці іноземних ключів НЕ індексуються (хоча відповідний первинний ключ індексується за визначенням). Індексація іноземного ключа, з цього приводу, шляхом індексації будь-якого ключа, а також приєднання таблиць до індексованих допомагає кращим показникам, а не приєднанням до неіндексованого ключа з обмеженням зовнішнього ключа.

Змінюючи тематику , якщо база даних просто підтримує показ веб-сайту / візуалізацію вмісту / тощо та записування кліків, тоді база даних з повними обмеженнями для всіх таблиць перестає вбивати для таких цілей. Подумай над цим. Більшість веб-сайтів навіть не використовують базу даних для таких. Для подібних вимог, коли дані просто записуються, а не посилаються на скажімо, використовуйте базу даних в пам'яті, яка не має обмежень. Це не означає, що немає моделі даних, так логічної моделі, але немає фізичної моделі даних.


Ну, я не знаю, чому вставлення 3 подвійних рядків замість пробілів і зміна двох слів вважається "67% Джонатана Леффлера", але я не думаю, що я зробив щось подібне на цьому. Основний текст надав @jay (користувач 183837).
Джонатан Леффлер

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

3

Додатковий привід для використання іноземних ключів: - Дозволяє більш багаторазово використовувати базу даних

Додатковий привід НЕ використовувати іноземні клавіші: - Ви намагаєтесь зафіксувати клієнта у своєму інструменті, зменшивши повторне використання.


3

З мого досвіду, завжди краще уникати використання FK в критичних додатках бази даних. Я б не погоджувався з хлопцями, які кажуть, що FKS - це хороша практика, але це не практично, коли база даних величезна і має величезні CRUD-операції / сек. Я можу поділитися, не називаючи ... один із найбільших інвестиційних банків не має єдиного ФК у базах даних. Ці обмеження обробляються програмістами під час створення програм із залученням БД. Основна причина - коли колись буде зроблено новий CRUD, він повинен здійснити кілька таблиць і перевірити кожну вставку / оновлення, хоча це не буде великою проблемою для запитів, що зачіпають окремі рядки, але це створює величезну затримку, коли ви маєте справу з пакетна обробка, яку повинен виконувати будь-який великий банк, як щоденні завдання.

Краще уникати ФК, але ризик повинен вирішуватися програмістами.


8
Я не думаю, що практика розвитку у великих банках встановлює золотий стандарт.
Адріан Костер

3

"Перш ніж додавати запис, перевірте, чи існує відповідна запис в іншій таблиці" - це бізнес-логіка.

Ось кілька причин, чому ви не хочете цього в базі даних:

  1. Якщо правила бізнесу змінюються, вам доведеться змінити базу даних. Базі даних потрібно буде відтворити індекс у багатьох випадках, і це відбувається повільно на великих таблицях. (Зміна правил включає: дозволяти гостям публікувати повідомлення або дозволяти користувачам видаляти свій обліковий запис, незважаючи на опубліковані коментарі тощо).

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

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

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


2

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

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


Джефф робить деякі хороші моменти. Однак Дан Чак у "Enterprise Rails" показує спосіб проектування таблиць кешу, які по суті є денормованою копією даних. Запити працюють швидко, і якщо таблицю не потрібно оновлювати, вона працює добре. Я вважаю, що якщо ваші дані керують поведінкою (наприклад, стан програми) вашої програми, вам потрібно максимально нормалізувати дані, оскільки в іншому випадку суперечливі дані призводять до непослідовної поведінки програми.
Джей Годсе

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

2

База даних «Уточнити» - це приклад комерційної бази даних, яка не має первинних чи зовнішніх ключів.

http://www.geekinterview.com/question_details/18869

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

Іншими словами, вони могли приєднатися до таблиць із явними деклараціями (DRI), але вони вирішили не робити цього .

Отже, база даних «Роз’яснення» повна невідповідностей, і вона недостатньо відповідає.

Але я припускаю, що це спростило роботу розробників, не потрібно писати код, щоб мати справу з референтною цілісністю, такою як перевірка відповідних рядків перед видаленням, додаванням.

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


Код для обробки помилкової референтної перевірки цілісності набагато менший, ніж код для обробки непослідовних даних.
Джей Годсе

@ Джей згоден! Не думаю, що я виступаю за такий підхід.
Ед Гінес

2

Я знаю лише бази даних Oracle, ніяких інших, і я можу сказати, що іноземні ключі є важливими для збереження цілісності даних. Перш ніж вставляти дані, потрібно скласти структуру даних та зробити їх правильними. Коли це зроблено - і таким чином всі первинні І зовнішні ключі будуть створені - робота зроблена!

Значення: осиротілі ряди? Ні. Ніколи в житті цього не бачив. Якщо тільки поганий програміст не забув іноземний ключ, або якщо він реалізував це на іншому рівні. Обидві - в умовах Oracle - величезні помилки, які призведуть до дублювання даних, осиротілих даних, а отже: до корупції. Я не уявляю базу даних без примусового використання FK. Мені це схоже на хаос. Це трохи схоже на систему дозволів Unix: уявіть, що всі кореневі. Подумайте про хаос.

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

Недоліки? Так, абсолютно! Тому що при вставці буде набагато більше перевірок. Але, якщо цілісність даних важливіша за ефективність, вона не вимагає. Проблема з продуктивністю в Oracle більше пов'язана з індексами, які поставляються з ПК та FK.


1

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

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

Я вважаю, що переваги використання ключів fireign переважають передбачувані недоліки.


5
Я, як правило, рідко видаляють речі. Просто позначте біт "Видимий / активний".
Дана

+1 за "Я вважаю, що переваги використання ключів fireign переважають передбачувані недоліки"
Ian Boyd

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

Зміна імені клієнта взагалі не буде болем, якщо ваш зовнішній ключ встановлений на CustomerId (ПК). в таблиці замовлень. Єдиний спосіб, яким буде біль, - якби FK було встановлено на CustomerName, що ніколи не повинно бути таким. ІМХО
KeyOfJ

1

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


6
Скільки часу на процесор витрачено на видалення повторюваних та непослідовних даних?
Ед Гінес

Так, це правда. У системі, над якою я працюю, ми повинні вставляти 10 - 40 гігів даних одночасно в базу даних, а продуктивність FK з і без видно за загальний час, який вона займає.
Пол Мендоса

1

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


9
Я вважаю, що реальною причиною обмежень ФК деякі не користуються (більшість, з моєї точки зору) - це сама лінь під притвором, що вони можуть захистити свій лінь аргументом економії ефективності. Я твердо переконаний, що переважна більшість витрат на тупість, що виникає в нашій компанії, пов'язана з недостатнім виконанням обмежень ФК та ​​ефектом пульсацій, який це має через компанію. Відсутність унікальних ключів - це інша річ, яка приводить мене в горіхи поряд із 2000+ лінійними процедурами, що зберігаються з 12 рівнями вкладених IF та випадковим відступом, але я зупинюсь зараз.
Чад

1

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

РЕДАКЦІЯ: Я здогадуюсь, на що він мав на увазі обмеження іноземних ключів, а не іноземні ключі як концепцію.


Ні. Йому не подобаються фактичні ключі!
ljs

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

Так, я був шокований, коли почув його. Однак він, можливо, ненавмисно затулився в щоку; можливо, він опублікує тут і уточнить на якомусь етапі :-)
ljs

1

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


1

Мені доводиться друге більшість коментарів тут, Іноземні ключі - це необхідні пункти для забезпечення цілісності даних. Різні варіанти ON DELETE та ON UPDATE дозволять вам обійти деякі "падіння", які тут згадують люди щодо їх використання.

Я вважаю, що в 99% усіх моїх проектів у мене буде ФК для забезпечення цілісності даних, проте трапляються такі рідкісні випадки, коли у мене є клієнти, ЯКІ ПОВИНЕН зберігати свої старі дані, незалежно від того, наскільки це погано ... але тоді я витрачаю багато часу на написання коду, який у будь-якому разі отримує лише дійсні дані, тому стає безглуздим.


1

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


1

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

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

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

Якщо ці функції включені, ваш код все одно буде імітувати їх, і ви втратите невелику продуктивність.

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


1

Я повторюю відповідь Дмитра - дуже добре.

Для тих, хто турбується про продуктивність, які часто надають накладні FK, є спосіб (в Oracle) ви можете отримати перевагу оптимізатора запитів обмеження FK без витрат на оплату витрат на перевірку обмежень під час вставлення, видалення або оновлення. Тобто створити обмеження FK з атрибутами RELY DISABLE NOVALIDATE. Це означає, що оптимізатор запитів ЗАБЕЗПЕЧУЄТЬСЯ, що обмеження було застосовано під час побудови запитів, без того, як база даних фактично примушує обмеження. Тут ви повинні бути дуже обережними, щоб взяти на себе відповідальність, коли ви заповнюєте таблицю з таким обмеженням FK, щоб абсолютно впевнитись, що у колонках (-ях) ФК немає даних, які порушують обмеження, як якщо б ви це зробили може отримати недостовірні результати за запитами, що стосуються таблиці, на якій вказане обмеження FK.

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


1

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

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

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


5
"програми ніколи не повинні оновлювати базу даних безпосередньо, а слід здійснювати через збережену процедуру. Це зберігає кодову базу всередині бази даних і означає, що база даних зберігає свою цілісність." <- Тут є припущення, що логіка в збережених процедурах не може порушити цілісність даних, що просто неправильно.
Тім Готьє

1

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

Але ось ще одна дуже хороша причина в реальному житті взагалі не використовувати іноземні ключі:

Ви розробляєте продукт, який повинен підтримувати різні системи баз даних.

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

Це може призвести до різних проблем:

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

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

Ви можете запитати: Кому потрібні різні системи баз даних? Що ж, не кожен може собі дозволити чи хоче повноцінно підірваний SQL-сервер на своїй машині. Це програмне забезпечення, яке потрібно підтримувати. Інші вже вклали час і гроші в якусь іншу систему БД. Безсерверна база даних чудово підходить для маленьких клієнтів лише на одній машині.

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


0

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


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

0

Один раз, коли ФК може викликати у вас проблему, це коли у вас є історичні дані, які посилаються на ключ (у таблиці пошуку), хоча ви більше не хочете, щоб ключ доступний.
Очевидно, що рішення полягає в тому, щоб розробити речі краще наперед, але я думаю про реальні ситуації тут, де ти не завжди маєш контроль над повним рішенням.
Наприклад: можливо, у вас є таблиця пошуку, в customer_typeякій перераховані різні типи клієнтів - скажімо, вам потрібно видалити певний тип клієнта, але (через ділові обмеження) не в змозі оновити клієнтське програмне забезпечення, і ніхто не враховував цю ситуацію. при розробці програмного забезпечення той факт, що він є іноземним ключем у якійсь іншій таблиці, може перешкодити вам видалити рядок, навіть якщо ви знаєте, що історичні дані, на які посилається, не мають значення.
Після того, як кілька разів спалили це, ви, ймовірно, відхилитесь від примусового виконання відносин.
(Я не кажу, що це добре - просто наводячи причину, чому ви можете вирішити уникати протипоказань FK та db взагалі)


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