Нужны ли внешние ключи в дизайне базы данных?

98

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

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

  • 2
    Это часто встречается здесь. Я обвиняю Джоэла Спольски :-). Здесь много хороших ответов; вместо того, чтобы перепечатывать мой, я просто дам вам ссылку: stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
  • 69
    «Предположим, программист на самом деле делает это правильно», - я даже не могу себе представить такой сценарий.
Показать ещё 13 комментариев
Теги:
database
foreign-keys

23 ответа

99
Лучший ответ

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

  • 49
    Если вам нужен индекс, создайте его, это не должно быть основной причиной для FK. (На самом деле в определенных обстоятельствах (например, больше вставок, чем выбирает) поддержание FK может выполняться медленнее.)
  • 4
    Это ужасный ответ. Обычно FKs могут добавить дополнительные накладные расходы, но не улучшить производительность.
Показать ещё 2 комментария
55

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

  • 2
    @ Грег Хьюгилл Это может привести к множеству проблем. Вы должны быть очень осторожны с такими мыслями, как DELETE CASCADE, так как во многих случаях вы хотите сохранить заказы, созданные пользователем при удалении пользователя.
  • 8
    Хотя это, вероятно, следует обрабатывать на уровне бизнес-логики. Решение о том, хранить ли связанные дочерние записи или нет, совсем не означает, что никакие значения не нарушают отношения внешнего ключа.
Показать ещё 2 комментария
43

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

Они не требуются, строго говоря, но преимущества огромны.

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

  • 41
    Джоэл: «До сих пор у нас никогда не было проблем». До сих пор я никогда не ездил на фонарный столб. Но я все еще думаю, что это хорошая идея, чтобы носить ремни безопасности ;-)
  • 2
    Может быть, вы никогда не видели проблему, но, может быть, она есть ... Большинство баз данных используют соглашение вроде id_xxx, которое точно такое же, как ixXXX
Показать ещё 7 комментариев
36

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

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

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

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

  • 2
    +1 за хорошую аналогию между инкапсуляцией и отношениями FK / PK.
20

Да.

  • Они держат вас честными.
  • Они держат новых разработчиков честными
  • Вы можете сделать ON DELETE CASCADE
  • Они помогают генерировать хорошие диаграммы, которые сами объясняют связи между таблицами.
  • 1
    что вы подразумеваете под честностью?
  • 0
    Я думаю, честно с концепцией. Это предотвращает вас от мошенничества с данными, делая быстрое и неэффективное программирование.
12

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

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

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

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

  • 2
    Хорошо, было бы неплохо объединить две таблицы с "ON [Relationship]" или каким-либо другим ключевым словом и позволить БД выяснить, какие столбцы задействованы. Кажется довольно разумным на самом деле.
12

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

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

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

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

  • 3
    +1 Для ключей постоянных, когда это возможно.
8

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

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

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

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

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

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

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

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

8

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

8

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

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

7

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 0
    Это отличный ответ.
5

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

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

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

4

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

4

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

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

3

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

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

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

Вопрос:

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

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

2

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

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

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

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

1

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

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

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

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

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

Удаление всех заказов и счетов удаленного клиента с помощью DEL DELETE CASCADE является прекрасным примером красивой, но неправильно разработанной схемы базы данных.

1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 0
    Ссылка не работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню