it-swarm-ru.tech

Что не так с внешними ключами?

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

Есть ли у людей веские причины для этого (чтобы избежать обсуждения в соответствии с принципами переполнения стека)?

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

246
ljs

Причины использования иностранных ключей:

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

Причины не использовать иностранные ключи:

  • вы заставляете БД работать на каждой операции CRUD , потому что она должна проверять согласованность FK. Это может быть очень дорого, если у вас много оттока
  • усиливая отношения, FK определяют порядок, в котором вы должны добавлять/удалять вещи, что может привести к отказу БД делать то, что вы хотите. (Разумеется, в таких случаях вы пытаетесь создать "Сиротскую строку", а это обычно не очень хорошо). Это особенно болезненно, когда вы выполняете большие пакетные обновления и загружаете одну таблицу перед другой, а вторая таблица создает согласованное состояние (но следует ли делать такие вещи, если есть вероятность, что вторая загрузка завершится неудачно, и ваша база данных сейчас несовместима?).
  • иногда вы заранее знаете, что ваши данные будут грязными, вы принимаете это и хотите, чтобы БД приняла их
  • ты просто ленивый :-)

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

341
SquareCog

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

Если, однако, вы не имели такого тщательного или позитивного опыта в прошлом, связанного с RDBMS, то, скорее всего, вы не сталкивались с такой информацией. Или, возможно, ваше прошлое включает погружение в среду, которая была громогласна против базы данных (например, "эти администраторы баз данных - идиоты - мы мало, мы выбрали несколько стропальщиков кода Java/c #, чтобы спасти день"), в этом случае вы можете быть категорически против к мистическим болтовням некоторых двебов, говорящих вам, что ФК (и ограничения, которые они могут подразумевать) действительно важны, если вы просто послушаете.

В детстве всех учили, что чистка зубов важна. Можете ли вы обойтись без этого? Конечно, но где-то внизу у вас будет меньше зубов, чем если бы вы чистили зубы после каждого приема пищи. Если бы мамы и папы были достаточно ответственны, чтобы охватить дизайн базы данных, а также гигиену полости рта, у нас не было бы этого разговора. :-)

78
Ed Lucas

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

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

52
AlexCuse

Внешние ключи обязательно для любой модели реляционной базы данных.

39
Galwegian

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

Также существует тот факт, что несколько систем обычно должны взаимодействовать напрямую с базой данных - от других систем, которые просто считывают данные (Crystal Reports), до систем, которые вставляют данные (необязательно с использованием разработанного мной API; это может быть написано тупой менеджер, который только что обнаружил VBScript и имеет пароль SA для блока SQL). Если база данных не настолько идиотобезопасна, как может быть, пока, пока, база данных.

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

29
Ant

Обновление : теперь я всегда использую внешние ключи. Мой ответ на возражение "они усложняют тестирование" состоит в том, чтобы "написать свои модульные тесты, чтобы им вообще не нужна база данных. Любые тесты, использующие базу данных, должны использовать ее должным образом, включая внешние ключи. Если установка болезненная, найти менее болезненный способ сделать настройку. "


Внешние ключи усложняют автоматизированное тестирование

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

Однако accounts имеет внешний ключ для contracts, а contracts имеет от fk до clients, а clients имеет от fk до cities, а cities имеет от fk до states.

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

На это есть как минимум две возможные перспективы:

  • "Это хорошо: ваш тест должен быть реалистичным, и эти ограничения данных будут существовать на производстве".
  • "Это плохо: вы должны иметь возможность тестировать отдельные части системы, не задействуя другие. Вы можете добавить интеграционные тесты для системы в целом".

Также возможно временно отключить проверки внешнего ключа во время выполнения тестов. MySQL, по крайней мере, поддерживает это .

18
Nathan Long

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

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

  • ON DELETE RESTRICT - Предотвращает удаление любых строк в другой таблице, имеющих ключи в этом столбце. Это то, что Кен Рэй описал выше.
  • ON DELETE CASCADE - Если строка в другой таблице удалена, удалите все строки в этой таблице, которые ссылаются на нее.
  • ON DELETE SET DEFAULT - Если строка в другой таблице удалена, установите любые внешние ключи, ссылающиеся на нее, по умолчанию для столбца.
  • ON DELETE SET NULL - Если строка в другой таблице удалена, установите для любых внешних ключей, ссылающихся на нее в этой таблице, значение null.
  • ON DELETE NO ACTION - Этот внешний ключ только отмечает, что это внешний ключ; а именно для использования в OR мапперах.

Эти же действия применимы и к ON UPDATE.

По умолчанию, похоже, зависит от того, какой sql сервер вы используете.

14
Powerlord

@imphasing - это именно тот тип мышления, который вызывает кошмары обслуживания.

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

14
Ed Guiness

Есть одна веская причина не использовать их: Если вы не понимаете их роль или то, как их использовать.

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

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

12
Kent Fredric

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

11
Matt Rogish

Более серьезный вопрос: вы бы поехали с завязанными глазами? Вот как это происходит, если вы разрабатываете систему без ограничений по ссылкам. Помните, что меняются бизнес-требования, изменения дизайна приложения, соответствующие логические предположения в коде, сама логика может быть реорганизована и т.д. В целом, ограничения в базах данных устанавливаются в соответствии с современными логическими предположениями, которые кажутся правильными для определенного набора логических утверждений и предположений.

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

К предмету этого листинга - внешний ключ сам по себе не "повышает производительность" и не "значительно снижает производительность" с точки зрения системы обработки транзакций в реальном времени. Однако в "пакетной" системе ВЫСОКОГО объема используется совокупная стоимость проверки ограничений. Итак, вот разница между процессом в реальном времени и процессом пакетной обработки; пакетная обработка - когда совокупные затраты, связанные с проверками ограничений, для последовательно обработанной партии представляют собой снижение производительности.

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

QUERY PERFORMANCE - если таблицы объединяются по внешним ключам, следует учитывать тот факт, что столбцы внешнего ключа НЕ УКАЗАНЫ (хотя соответствующий первичный ключ индексируется по определению). Индексирование внешнего ключа, в этом отношении, индексация любого ключа и присоединение таблиц к индексированным помогает повысить производительность, а не присоединение к неиндексированному ключу с ограничением внешнего ключа.

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

5
jasbir L

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

Лучше избегать ФК, но его риск должен быть решен программистами.

3
Rachit

"Перед добавлением записи убедитесь, что соответствующая запись существует в другой таблице" - это бизнес-логика.

Вот несколько причин, по которым вы не хотите этого в базе данных:

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

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

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

  4. Повторное использование вашей логики с различными источниками данных. Если в базе данных нет логики, мое приложение может создавать объекты из записей из базы данных, создавать их из веб-службы, файла json или любого другого источника. Мне просто нужно поменять реализацию картографа данных и использовать всю мою бизнес-логику с любым источником. Если в базе данных есть логика, это невозможно, и вам необходимо реализовать логику на уровне отображения данных или в бизнес-логике. В любом случае, вам нужны эти проверки в вашем коде. Если в базе данных нет логики, я могу развернуть приложение в разных местах, используя разные реализации базы данных или плоских файлов.

3
Tom B

Дополнительная причина для использования внешних ключей: - Позволяет большее повторное использование базы данных

Дополнительная причина НЕ использовать иностранные ключи: - Вы пытаетесь заблокировать клиента в своем инструменте, уменьшая повторное использование.

3
Dan

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

В нескольких словах денормализованная база данных может быть быстрее при обработке огромных объемов данных; и вы можете не заботиться о точной согласованности в зависимости от приложения, но это заставляет вас быть намного более осторожным при работе с данными, поскольку БД не будет.

2
Santiago Palladino

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

Значение: осиротевшие строки? Нет. Никогда не видел этого в моей жизни. Если только плохой программист не забыл внешний ключ или не реализовал его на другом уровне. И то, и другое - в контексте Oracle - огромные ошибки, которые приведут к дублированию данных, потерям данных и, следовательно, к повреждению данных. Я не могу представить базу данных без применения ФК. Это похоже на хаос для меня. Это немного похоже на систему разрешений Unix: представьте, что все - root. Подумай о хаосе.

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

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

2
tvCa

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

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

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

1
Ken Ray

Я должен повторить большинство комментариев здесь. Внешние ключи являются необходимыми элементами для обеспечения целостности ваших данных. Различные опции для ON DELETE и ON UPDATE позволят вам обойти некоторые "падения", которые люди упоминают здесь относительно их использования.

Я обнаружил, что в 99% всех моих проектов у меня есть FK для обеспечения целостности данных, однако есть те редкие случаи, когда у меня есть клиенты, которые ДОЛЖНЫ хранить свои старые данные, независимо от того, насколько они плохие .... но потом я трачу много времени на написание кода, который в любом случае получает только действительные данные, так что это становится бессмысленным.

1
Mitchel Sellers

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

EDIT: Я думаю, он имел в виду ограничения внешнего ключа , а не внешние ключи как концепцию.

1
lordscarlet

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

1
remonedo

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

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

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

Другими словами, они могли объединить таблицы с явными декларациями (DRI), но они решили не .

Следовательно, база данных Clarify полна несоответствий и неэффективна.

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

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

1
Ed Guiness

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

Но вот еще одна очень хорошая причина из реальной жизни вообще не использовать внешние ключи:

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

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

Это может привести к различным проблемам:

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

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

Вы можете спросить: кому нужны разные системы баз данных? Ну, не каждый может позволить себе или хочет полноценный SQL-сервер на своей машине. Это программное обеспечение, которое необходимо поддерживать. Другие уже вложили время и деньги в какую-то другую систему БД. Бессерверная база данных отлично подходит для небольших клиентов только на одном компьютере.

Никто не знает, как ведут себя все эти системы БД, но ваша бизнес-логика с проверками целостности всегда остается неизменной.

1
Michael

Я повторяю ответ Дмитрия - очень хорошо сказано.

Для тех, кого беспокоит нехватка производительности, которую часто приносят FK, есть способ (в Oracle) получить преимущество оптимизатора запросов от ограничения FK без дополнительных затрат на проверку ограничения во время вставки, удаления или обновления. То есть создать ограничение FK с атрибутами RELY DISABLE NOVALIDATE. Это означает, что оптимизатор запросов ПРИНИМАЕТ, что ограничение было применено при построении запросов без фактического применения ограничения базой данных. Вы должны быть очень осторожны, чтобы взять на себя ответственность, когда вы заполняете таблицу с помощью ограничения FK, как это, чтобы быть абсолютно уверенным, что у вас нет данных в ваших столбцах FK, которые нарушают ограничение, как если бы вы это сделали может получить ненадежные результаты из запросов, включающих таблицу, к которой относится это ограничение FK.

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

1
Mike McAllister

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

1
Arno

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

1
CodeRot

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

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

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

1
Zak

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

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

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

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

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

1
Eric

Однажды, когда FK может вызвать у вас проблему, это когда у вас есть исторические данные, которые ссылаются на ключ (в таблице поиска), даже если вы больше не хотите, чтобы ключ был доступен.
Очевидно, что решение состоит в том, чтобы лучше спроектировать вещи заранее, но я думаю о реальных ситуациях, когда вы не всегда можете полностью контролировать решение.
Например: возможно, у вас есть справочная таблица customer_type, в которой перечислены различные типы клиентов - допустим, вам нужно удалить определенный тип клиентов, но (из-за ограничений бизнеса) не удается обновить программное обеспечение клиента И никто не обращал внимания на эту ситуацию при разработке программного обеспечения, тот факт, что это внешний ключ в какой-то другой таблице, может помешать вам удалить строку, даже если вы знаете исторические данные, которые ссылаются на это, не имеет значения.
После того, как вы несколько раз обожгли это, вы, вероятно, отстранитесь от навязывания отношений с БД.
(Я не говорю, что это хорошо - просто приведу причину, по которой вы можете решить избегать FKs и db-ограничений вообще)

0
hamishmcn

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

Возьмите следующую таблицу

Адрес

  • AddressId (PK)
  • EntityId
  • Тип объекта
  • Город
  • Государственный
  • Страна
  • Так далее..

Возможными значениями EntityType могут быть Employee, Company, Customer, и EntityId ссылается на первичный ключ любой таблицы, которая вас интересует.

Я не думаю, что это лучший способ сделать что-то, но это сработало для этого проекта.

0
Curtis

Как и многие вещи, это компромисс. Вопрос в том, где вы хотите выполнить работу по проверке целостности данных:

(1) использовать внешний ключ (единая точка для настройки таблицы, функция уже реализована, протестирована, проверена на работоспособность)

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

Для базы данных более эффективно выполнять (2), проще поддерживать и меньше рисковать с (1).

0
Jen A

Я повторю то, что сказал Дмитрий, но добавлю точку.

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

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

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

0
typicalrunt

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

0
Senthil

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

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

Однако во многих случаях эти ограничения могут изменяться во время выполнения. Например, у вас может быть таблица "cars" с атрибутом "color" в качестве атрибута, который изначально принимает значения, скажем, "red", "green" и "blue". Во время выполнения программы возможно добавить действительные цвета в этот начальный список, и новые добавленные "автомобили" могут иметь любой цвет в текущем списке цветов. Кроме того, вы обычно хотите, чтобы этот обновленный список цветов пережил перезапуск программы.

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

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

0
Jay Godse

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

0
Kilhoffer

Q довольно часто мы получаем ошибки с помощью ограничения FK Не удается добавить или обновить дочернюю строку: ограничение внешнего ключа не выполнено. Предположим, есть две таблицы inventory_source и contract_lines, и мы ссылаются inventory_source_id в contract_lines из inventory_source и предположим, что мы хотим удалить запись из inventory_source и запись уже присутствует в contract_lines или мы хотим удалить столбец PK из базовой таблицы мы получаем ошибки для ограничений FK, мы можем избежать этого, используя шаги, указанные ниже.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Мы можем преодолеть это, используя следующие шаги:

  1. При удалении или обновлении строки из источника_оценки автоматически удаляются или обновляются соответствующие строки в таблице contract_lines, что называется каскадным удалением или обновлением.
  2. Еще один способ сделать это - установить для столбца i.e inventory_source_id в таблице contract_lines значение NULL, когда соответствующая ему запись удаляется в таблице inventory_source.
  3. Мы можем ограничить родительскую таблицу для удаления или обновления, другими словами, можно отклонить операцию удаления или обновления для таблицы inventory_source.
  4. Попытка удалить или обновить значение первичного ключа не будет разрешена, если в указанной таблице есть соответствующее значение внешнего ключа.
0
Vikas Kukreti