Чи справді потрібні сторонні ключі в дизайні бази даних?


109

Наскільки мені відомо, зовнішні клавіші (FK) використовуються для допомоги програмісту в правильному маніпулюванні даними. Припустимо, програміст насправді робить це правильним чином, то чи насправді нам потрібна концепція іноземних ключів?

Чи є якісь інші способи використання іноземних ключів? Я щось тут пропускаю?


2
Це часто виникає тут. Я звинувачую Джоела Спольського :-). Тут є багато хороших відповідей; а не передруковувати мій, я просто дам вам посилання: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog

70
"Припустимо, програміст насправді робить це правильно" - я навіть не можу уявити такий сценарій.
рекурсивна

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

5
@lubos & cdeszaq. Власне, це правило реляції ... це підмножина правила 10 Кодда "Заповіді Twleve" ... "Незалежність цілісності", яке в основному говорить про те, що реляційна цілісність RDBMS повинна підтримуватися незалежно від будь-якої програми, що звертається до неї. це саме те, що я пояснював легко зрозумілим способом. Це правило реалізується, серед іншого, зовнішніми ключовими обмеженнями. Так що так, ідея зовнішнього ключа - це "відносне" правило.
Трайнко

1
@lubos: Щоб уточнити, ви говорите про те, чи збираєтесь ви використовувати певну функцію, але я говорю про те, чи потрібна наявність цієї функції для повноцінного функціонування RDBMS. Референтні обмеження, якщо і коли ви вирішите їх використовувати, - це те, що слід застосовувати в межах RDBMS (а не програми), тому це має бути функція, і в цьому сенсі це вимога реляційної моделі, якщо Ви збираєтеся розробити повну RDBMS.
Трайнко

Відповіді:


102

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


52
Якщо вам потрібно створити індекс, це не повинно бути основною причиною для ФК. (Насправді за певних обставин (Більше вставок, ніж вибрано, наприклад) підтримка FK може бути повільнішою.)
Роберт,

7
Це жахлива відповідь. FKs загалом може додати додаткові накладні витрати, а не покращити продуктивність.
Agile Jedi

У SQL-сервері вони не індексуються за замовчуванням ні на арбітра, ні на реферала. sqlskills.com/blogs/kimberly/…
user420667

1
Ні в Oracle; індекси (у стовпцях FK) потрібно створити самостійно.
Маленький

58

Іноземні ключі також можуть допомогти програмісту писати менше коду, використовуючи такі речі ON DELETE CASCADE. Це означає, що якщо у вас є одна таблиця, яка містить користувачів, та інша, що містить замовлення чи щось подібне, видалення користувача може автоматично видалити всі замовлення, які вказують на цього користувача.


3
@Greg Hewgill Це може потенційно призвести до багатьох проблем. Вам слід бути дуже обережними з такими думками, як DELETE CASCADE, оскільки у багатьох випадках ви хочете зберегти замовлення, створені користувачем при видаленні користувача.
Кіббі

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

5
Інша проблема - аудит, якщо аудит не проводиться на рівні db, каскадні оновлення або видалення недійсні для вашого аудиторського сліду.
si618

@Codewerks: бізнес-логіка може бути в БД.
Fantius

44

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

Вони не потрібні , строго кажучи, але користі величезні.

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


43
Джоел: "Поки у нас ніколи не було проблем". Поки що я ніколи не заїжджав у ліхтарик. Але я все ще думаю, що це гарна ідея надіти ремені безпеки ;-)
Тоні Ендрюс

2
Можливо, ви ніколи не бачили проблеми, але може бути, вона там є ... Більшість баз даних використовують такий конвент, як id_xxx, який точно такий же, як ixXXX
FerranB

1
@Joel: Іменування конвенцій замість виконання правил? Можливо, також ухиляйтесь від типу, поки ви на це.
jcollum

8
@Eric: Ви тримаєте Fog Creek як якийсь аватар розробки програмного забезпечення тут. Якби ви сказали: "У компанії в Нью-Йорку немає сторонніх ключів у їхньому дебіле ...", ми б всі сказали "А?"
jcollum

3
Ерік: FogBugz використовує режим іменування для зовнішніх ключів. Наприклад, ixBug розуміється як індекс в первинному ключі помилки таблиці. Поки у нас ніколи не було проблем. - Джоель Спольський
Сем Шафрон

40

Схема бази даних без обмежень FK - це як їзда без ременів безпеки.

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

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

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


2
+1 за хорошу аналогію між інкапсуляцією та відносинами FK / PK.
jcollum

21

Так.

  1. Вони тримають вас чесно
  2. Вони тримають нових розробників чесними
  3. Ви можете зробити ON DELETE CASCADE
  4. Вони допомагають створювати приємні діаграми, які самостійно пояснюють зв’язки між таблицями

1
що ви маєте на увазі під чесністю?
dspacejs

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

13

Припустимо, програміст насправді робить це правильним чином

Зробити таке припущення мені здається вкрай поганою ідеєю; в цілому програмне забезпечення феноменально баггі.

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

Хоча в ідеальному світі природні об'єднання використовуватимуть відносини (тобто обмеження FK), а не відповідність імен стовпців. Це зробить ФК ще кориснішими.


2
Хороший момент, було б непогано з'єднати дві таблиці з "ON [відносини]" або яким-небудь іншим ключовим словом і дозволити db розібратися, в яких стовпцях йде мова. Насправді здається досить розумним.
jcollum

13

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

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

@John - Інші бази даних можуть автоматично створювати індекси для сторонніх ключів, але SQL Server цього не робить. У SQL Server зв'язки із зовнішніми ключами є лише обмеженнями. Ви повинні окремо визначити свій індекс на зовнішніх ключах (що може принести користь.)

Редагувати: Я хотів би додати, що, IMO, використання сторонніх ключів для підтримки ON DELETE або ON UPDATE CASCADE - це не обов'язково. На практиці я виявив, що каскад при видаленні слід ретельно враховувати на основі взаємозв'язку даних - наприклад, чи є у вас природний батько-дитина, де це може бути нормально, або пов'язана таблиця - це набір значень пошуку. Використання каскадних оновлень означає, що ви дозволяєте змінювати первинний ключ однієї таблиці. У цьому випадку я маю загальну філософську незгоду в тому, що первинний ключ таблиці не повинен змінюватися. Ключі повинні бути за своєю суттю постійними.


9

Без стороннього ключа, як ви можете сказати, що два записи в різних таблицях пов'язані?

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


8

Чи є користь у відсутності сторонніх ключів? Якщо ви не використовуєте шалену базу даних, налаштування FK не так складно налаштувати. То чому б ви мали політику уникати їх? Одна річ - мати назву про іменування, яка каже, що стовпець посилається на інше, це ще одне знати, що база даних насправді підтверджує це співвідношення для вас.


8

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

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

Теоретично ні. Однак ніколи не було жодного програмного забезпечення без помилок.

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

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

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

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

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


7

FK дуже важливі і завжди повинні існувати у вашій схемі, якщо ви не eBay .


2
це посилання насправді надзвичайно захоплююче ... Мені б справді хотілося дізнатися більше деталей, і я трохи боюся використовувати ebay зараз. для інших людей: натисніть на четверте запитання, щоб побачити, що він говорить про їх структуру db. все ж інтерв'ю варто переглянути, хоча. також ...unibrow
похмурий.penguin

6

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

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

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

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


2
Це як цибуля. ФК - останній шар захисту. Якщо це не вбудована локальна база даних, програми, які намагаються зробити референтну цілісність, завжди є поганою ідеєю.
Fabricio Araujo

5

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

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

Іноземні ключі дозволять їм зрозуміти структуру бази даних, не перебираючи тисячі рядків коду.


5

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

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

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

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

Чи є якісь інші способи використання іноземних ключів? Я щось тут пропускаю?

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


Це чудова відповідь.
Ден Лугг

4

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

Налагодити помилку обмеження у FK набагато приємніше, ніж реконструювати видалення, яке порушило вашу програму.


4

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


3

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

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

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

Питання:

Чи є якісь інші способи використання іноземних ключів? Я щось тут пропускаю?

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


2

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

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

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

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


1

Ви можете розглянути зовнішні ключі як обмеження,

  • Допоможіть зберегти цілісність даних
  • Покажіть, як дані пов’язані між собою (що може допомогти у дотриманні бізнес-логіки та правил)
  • При правильному використанні це може допомогти підвищити ефективність, з якою дані отримуються з таблиць.

1

Зараз ми не використовуємо іноземні ключі. І ми здебільшого не шкодуємо про це.

Це сказало - ми, швидше за все, найближчим часом почнемо використовувати їх набагато більше з кількох причин, обидві з подібних причин:

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

  2. Підтримка інструментів. Набагато простіше побудувати моделі даних за допомогою Visual Studio 2008, які можна використовувати для LINQ до SQL, якщо є належні зовнішні ключові зв’язки.

Тому я гадаю, що ми виявили, що якщо ми робимо багато ручної роботи з SQL (побудувати запит, запустити запит, blahblahblah), іноземні ключі не обов'язково необхідні. Коли ви починаєте користуватися інструментами, вони стають набагато кориснішими.


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

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

1

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

Щодо коду, ми зазвичай просто кудись кинемо виняток - але в SQL ми зазвичай отримуємо "неправильні" відповіді.

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


Обмеження унікальності вказують на високу кардинальність, яку оптимізатор використовує при виборі механізму з'єднання.
Пітер Вон

1

Іноземні ключі ніколи не були явними (таблиця (стовпець) ІНФОРМАЦІЙНИХ КЛЮЧІВ), заявлені в проектах (бізнес-додатки та веб-сайти соціальних мереж), над якими я працював.

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

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

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

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

Видалення всіх замовлень та рахунків видаленого клієнта за допомогою ON DELETE CASCADE є ідеальним прикладом красивої, але неправильно розробленої схеми бази даних.


0

Так. ON DELETE [RESTRICT | CASCADE] утримує розробників від обміну даними, зберігаючи дані чистими. Нещодавно я приєднався до команди розробників Rails, яка не зосереджувалась на обмеженнях бази даних, таких як зовнішні ключі.

На щастя, я знайшов це: http://www.redhillonrails.org/foreign_key_associations.html - плагіни RedHill on Ruby on Rails генерують сторонні ключі, використовуючи умову щодо стилю конфігурації . Міграція з product_id створить зовнішній ключ до ідентифікатора в таблиці продуктів .

Ознайомтеся з іншими чудовими плагінами на RedHill , включаючи міграцію, завершену в транзакціях.


0

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

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