Действительно ли внешние ключи необходимы при проектировании базы данных?

109

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

Есть ли другие способы использования внешних ключей? Я что-то упустил?

Нияз
источник
2
Это часто случается здесь. Я виню Джоэла Спольски :-). Здесь есть много хороших ответов; вместо того, чтобы перепечатывать мой, я просто дам вам ссылку: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
SquareCog
70
«Предположим, что программист уже делает это правильно» - я даже не могу представить себе такой сценарий.
рекурсивный
11
«Внешний ключ» - это идея, а не технология. Это правило отношений. На самом деле ваш вопрос заключается в том, следует ли вам пытаться применить правило в своем коде или позволить базе данных помочь вам. Когда задействован параллелизм, лучше всего позволить ядру базы данных применять правило, поскольку он знает ВСЕ, что происходит в базе данных, в то время как ваш код может не знать.
Трийнко
5
@lubos и cdeszaq. На самом деле, это реляционное правило ... это подмножество правила 10 "Двенадцати заповедей" Кодда ... "Независимость целостности", которое в основном гласит, что реляционная целостность СУБД должна поддерживаться независимо от любого приложения, которое обращается к ней, которое это именно то, что я объяснял простым для понимания способом. Это правило реализуется, помимо прочего, ограничениями внешнего ключа. Итак, да, идея внешнего ключа - это «реляционное правило».
Трийнко
1
@lubos: Чтобы уточнить, вы говорите о том, собираетесь ли вы использовать определенную функцию, но я говорю о том, необходимо ли присутствие этой функции для создания полной, полнофункциональной СУБД. Реляционные ограничения, если и когда вы решите их использовать, должны быть реализованы в РСУБД (а не в приложении), поэтому это функция, которая должна присутствовать, и в этом смысле это требование реляционной модели, если вы собираетесь разработать полную СУБД.
Трийнко 01

Ответы:

102

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

Джон Топли
источник
52
Если вам нужен индекс, создающий его, это не должно быть основной причиной для FK. (На самом деле, при определенных обстоятельствах (например, больше вставок, чем выборок) поддержание FK может быть медленнее.)
Роберт
7
Это ужасный ответ. FK обычно могут добавить дополнительные накладные расходы, но не улучшить производительность.
Agile Jedi,
В SQL-Server они по умолчанию не индексируются ни для рефери, ни для реферера. sqlskills.com/blogs/kimberly/…
user420667
1
Ни в Oracle; вы должны сами создавать индексы (по столбцам FK).
Littlefoot
58

Внешние ключи также могут помочь программисту писать меньше кода, используя такие вещи, как ON DELETE CASCADE. Это означает, что если у вас есть одна таблица, содержащая пользователей, а другая - заказы или что-то в этом роде, то удаление пользователя может автоматически удалить все заказы, которые указывают на этого пользователя.

Грег Хьюгилл
источник
3
@Greg Hewgill Это может привести к множеству проблем. Вы должны быть очень осторожны с такими мыслями, как DELETE CASCADE, поскольку во многих случаях вы захотите сохранить заказы, созданные пользователем при удалении пользователя.
Kibbee
8
Хотя это, вероятно, следует обрабатывать на уровне бизнес-логики. Решение о том, следует ли хранить связанные дочерние записи, не совсем то же самое, что гарантировать, что никакие значения не нарушают отношения внешнего ключа.
Codewerks, 06
5
Другая проблема - это аудит. Если аудит не выполняется на уровне базы данных, каскадные обновления или удаления сделают ваш контрольный журнал недействительным.
si618 01
@Codewerks: Бизнес-логика может быть в БД.
Fantius 01
44

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

Строго говоря, они не требуются , но выгода огромна.

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

Эрик Зи Берд
источник
43
Джоэл: «Пока у нас никогда не было проблем». Пока ни разу не заехал в фонарный столб. Но я все же считаю, что пристегивать ремни безопасности
Тони Эндрюс
2
Может быть, вы никогда не ВИДИЛИ проблему, но, возможно, она есть ... Большинство баз данных используют соглашение, подобное id_xxx, которое точно такое же, как ixXXX
FerranB
1
@Joel: Соглашения об именах вместо соблюдения правил? Можно также покончить с шрифтом, пока вы занимаетесь этим.
jcollum
8
@Eric: Вы представляете Fog Creek как своего рода аватар разработчиков программного обеспечения. Если бы вы сказали: «У компании в Нью-Йорке нет внешних ключей в своей базе данных ...», мы бы все сказали «И?»
jcollum
3
Эрик: FogBugz использует соглашение об именах для внешних ключей. Например, ixBug понимается как индекс первичного ключа таблицы Bug. Пока у нас никогда не было проблем. - Джоэл Спольски
Сэм Саффрон
40

Схема базы данных без ограничений FK похожа на вождение без ремня безопасности.

Однажды ты пожалеешь об этом. Не тратить лишнее время на основы дизайна и целостность данных - верный способ избавиться от головной боли в дальнейшем.

Вы бы приняли такой небрежный код в своем приложении? Это напрямую обращалось к объектам-членам и напрямую изменяло структуры данных.

Как вы думаете, почему это стало трудным и даже неприемлемым в современных языках?

Парень
источник
2
+1 для хорошей аналогии между инкапсуляцией и отношениями FK / PK.
jcollum
21

Да.

  1. Они сохраняют честность
  2. Они сохраняют честность новых разработчиков
  3. Ты можешь сделать ON DELETE CASCADE
  4. Они помогают вам создавать красивые диаграммы, которые сами объясняют связи между таблицами.
csmba
источник
1
что вы имеете в виду под честностью?
dspacejs 06
Я думаю, честно с концепцией. Это предохраняет вас от обмана данных, выполняя быстрое и неубедительное программирование.
Орест Вирон
13

Предположим, что программист уже делает это правильно.

Такое предположение кажется мне крайне плохой идеей; в общем софт феноменально глючный.

И в этом-то и дело. Разработчики не могут все сделать правильно, поэтому обеспечение того, чтобы база данных не была заполнена плохими данными, - это хорошо.

Хотя в идеальном мире естественные объединения будут использовать отношения (т.е. ограничения FK), а не сопоставление имен столбцов. Это сделало бы FK еще более полезными.

DrPizza
источник
2
Хороший момент, было бы неплохо объединить две таблицы с помощью «ON [Relationship]» или какого-либо другого ключевого слова и позволить базе данных выяснить, какие столбцы задействованы. На самом деле кажется довольно разумным.
jcollum
13

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

Ограничения до внешнего ключа (также известные как декларативная ссылочная целостность или DRI) много времени было потрачено на реализацию этих отношений с помощью триггеров. Тот факт, что мы можем формализовать отношения с помощью декларативного ограничения, очень важен.

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

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

Питер Мейер
источник
9

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

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

samjudson
источник
8

Есть ли преимущество в отсутствии внешних ключей? Если вы не используете дрянную базу данных, FK не так уж сложно настроить. Так почему бы вам избегать их? Одно дело иметь соглашение об именах, которое гласит, что столбец ссылается на другой, другое - знать, что база данных действительно проверяет эту связь за вас.

Тундей
источник
8

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

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

Теоретически нет. Однако никогда не было программного обеспечения без ошибок.

Ошибки в коде приложения обычно не так опасны - вы определяете ошибку и исправляете ее, и после этого приложение снова работает без сбоев. Но если ошибка позволяет обработанным данным попасть в базу данных, то вы застряли с ней! Восстановить поврежденные данные в базе данных очень сложно.

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

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

Если ограничения закодированы в базе данных, худшее, что может случиться с ошибками, - это то, что пользователю будет показано уродливое сообщение об ошибке о том, что какое-то ограничение SQL не выполнено. Это гораздо предпочтительнее, чем позволить сокращению данных в вашей корпоративной базе данных, где это, в свою очередь, нарушит работу всех ваших приложений или просто приведет к разного рода неправильным или вводящим в заблуждение результатам.

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

JacquesB
источник
7

FK очень важны и всегда должны присутствовать в вашей схеме, если вы не eBay .

cherouvim
источник
2
эта ссылка на самом деле чрезвычайно увлекательна ... я действительно хотел бы узнать больше, и мне немного страшно использовать ebay сейчас. для других людей: нажмите на 4-й вопрос, чтобы узнать, что он говорит об их структуре БД. все же интервью стоит посмотреть. также ...unibrow
gloomy.penguin
6

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

Например, Ruby on Rails не использует внешние ключи, но сам проверяет все отношения. Если вы когда-либо обращаетесь к своей базе данных только из этого приложения Ruby on Rails, это нормально.

Однако, если у вас есть другие клиенты, которые пишут в базу данных, то без внешних ключей им необходимо реализовать собственную проверку. Затем у вас есть две копии кода проверки, которые, скорее всего, отличаются, что любой программист должен уметь сказать, что это кардинальный грех.

На этом этапе действительно необходимы внешние ключи, поскольку они позволяют снова перенести ответственность на одну точку.

Орион Эдвардс
источник
2
Это как лук. ФК - последний уровень защиты. Если это не встроенная локальная база данных, приложения, пытающиеся обеспечить ссылочную целостность, всегда плохая идея.
Фабрицио Араухо,
5

Внешние ключи позволяют тому, кто раньше не видел вашу базу данных, определить отношения между таблицами.

Сейчас все может быть хорошо, но подумайте, что будет, когда ваш программист уйдет, а его место займет кто-то другой.

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

Craig
источник
5

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

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

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

Программисты смертны и подвержены ошибкам. FK декларативны, поэтому их сложнее испортить .

Есть ли другие способы использования внешних ключей? Я что-то упустил?

Хотя они были созданы не для этого, FK обеспечивают надежные подсказки для инструментов построения диаграмм и построителей запросов. Это передается конечным пользователям, которые отчаянно нуждаются в надежных подсказках.

Питер Вон
источник
Это отличный ответ.
Дэн Лагг
4

Они не являются строго необходимыми, так же как и ремни безопасности. Но они действительно могут спасти вас от глупостей, которые могут испортить вашу базу данных.

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

Марк Харрисон
источник
4

Они важны, потому что ваше приложение - не единственный способ манипулировать данными в базе данных. Ваше приложение может обрабатывать ссылочную целостность так честно, как оно того хочет, но все, что для этого требуется, - это один бозо с нужными привилегиями, чтобы подойти и выдать команду вставки, удаления или обновления на уровне базы данных, и все ваше приложение может обойти ссылочную целостность. Внесение ограничений FK на уровне базы данных означает, что, если этот бозо не решает отключить ограничение FK перед выдачей своей команды, ограничение FK приведет к сбою неправильного оператора вставки / обновления / удаления с нарушением ссылочной целостности.

Майк Макаллистер
источник
3

Я думаю об этом с точки зрения затрат / выгод ... В MySQL добавление ограничения - это одна дополнительная строка DDL . Это всего лишь несколько ключевых слов и пара секунд размышлений. На мой взгляд, это единственная «цена» ...

Инструменты любят внешние ключи. Внешние ключи предотвращают появление неверных данных (т. Е. Потерянных строк), которые не могут повлиять на бизнес-логику или функциональность и, следовательно, остаются незамеченными и накапливаются. Это также мешает разработчикам, незнакомым со схемой, реализовывать целые фрагменты работы, не осознавая, что у них отсутствует взаимосвязь. Возможно, в рамках вашего текущего приложения все отлично, но если вы что-то пропустили, и когда-нибудь будет добавлено что-то неожиданное (подумайте о необычных отчетах), вы можете оказаться в таком месте, где вам придется вручную очистить плохие данные, которые накапливались с момента создания схемы без принудительной проверки базы данных.

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

Вопрос:

Есть ли другие способы использования внешних ключей? Я что-то упустил?

Немного загружено. Вставляйте комментарии, отступы или имена переменных вместо «внешних ключей» ... Если вы уже прекрасно понимаете предмет, о котором идет речь, это «бесполезно» для вас.

данб
источник
2

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

Когда мы делаем предположение, например: каждый заказ имеет клиент , что предположение должно быть взыскано на что - то . В базах данных этим «чем-то» являются внешние ключи.

Я думаю, что это стоит компромисса в скорости разработки. Конечно, без них можно писать код быстрее, и, вероятно, поэтому некоторые люди их не используют. Лично я убил несколько часов с NHibernate и некоторым ограничением внешнего ключа, которое злится, когда я выполняю какую-то операцию. ОДНАКО, я знаю, в чем проблема, поэтому это не проблема. Я использую обычные инструменты, и есть ресурсы, которые помогут мне обойти эту проблему, возможно, даже люди, которые могут помочь!

Альтернативный вариант - позволить ошибке проникнуть в систему (и при наличии достаточного времени это произойдет), когда внешний ключ не установлен, и ваши данные становятся несовместимыми. Затем вы получите необычный отчет об ошибке, исследуйте и «ОН». База данных прикручена. Теперь, сколько времени потребуется, чтобы это исправить?

Quibblesome
источник
1

Вы можете рассматривать внешние ключи как ограничение, которое,

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

В настоящее время мы не используем внешние ключи. И по большей части мы не жалеем об этом.

Тем не менее - мы, вероятно, начнем использовать их гораздо больше в ближайшем будущем по нескольким причинам, обе по схожим причинам:

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

  2. Поддержка инструмента. С помощью Visual Studio 2008 намного проще создавать модели данных, которые можно использовать для LINQ to SQL, если существуют правильные отношения внешних ключей.

Итак, я полагаю, что моя точка зрения состоит в том, что мы обнаружили, что если мы делаем много ручной работы с SQL (создание запроса, выполнение запроса, бла-бла-бла), внешние ключи не обязательно необходимы. Однако, как только вы начнете пользоваться инструментами, они станут намного полезнее.

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

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

В коде мы обычно просто получаем где-то исключение, но в SQL мы обычно просто получаем «неправильные» ответы.

Теоретически SQL Server мог бы использовать ограничения как часть плана запроса, но, за исключением проверочных ограничений для секционирования, я не могу сказать, что когда-либо действительно был свидетелем этого.

Марк Брэкетт
источник
Ограничения уникальности указывают на высокую мощность, которая используется оптимизатором при выборе механизма соединения.
Питер Вон,
1

Внешние ключи никогда не были явными (таблица FOREIGN KEY REFERENCES (столбец)), объявленными в проектах (бизнес-приложения и веб-сайты социальных сетей), над которыми я работал.

Но всегда существовало некое соглашение об именах столбцов, которые были внешними ключами.

Это похоже на нормализацию базы данных - вы должны знать, что вы делаете и каковы последствия этого (в основном производительность).

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

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

Удаление всех заказов и счетов-фактур удаленного клиента с помощью 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, вы полностью теряете возможность генерировать иерархическую модель без внешних ключей.

Майк Гриффин
источник