Я помню, как Джоэл Спольски упоминал в подкасте 014, что он почти никогда не использовал внешний ключ (если я правильно помню). Однако мне кажется, что они очень важны, чтобы избежать дублирования и последующих проблем с целостностью данных в вашей базе данных.
Есть ли у людей веские причины для этого (чтобы избежать обсуждения в соответствии с принципами переполнения стека)?
Ответы:
Причины использования иностранных ключей:
Причины не использовать иностранные ключи:
Я думаю (я не уверен!), Что большинство установленных баз данных предоставляют способ указать внешний ключ, который не применяется, и это просто немного метаданных. Поскольку неисполнение устраняет все причины не использовать FK, вам, вероятно, следует пойти по этому пути, если применима какая-либо из причин во втором разделе.
источник
Это вопрос воспитания. Если где-то в своей образовательной или профессиональной карьере вы проводили время, питая и ухаживая за базами данных (или работали в тесном контакте с талантливыми людьми, которые это делали), то фундаментальные принципы сущностей и отношений хорошо укоренились в вашем мыслительном процессе. Среди этих зачатков - как / когда / почему указывать ключи в вашей базе данных (первичные, внешние и, возможно, альтернативные). Это вторая натура.
Если, однако, вы не имели такого тщательного или позитивного опыта в прошлом, связанного с RDBMS, то, скорее всего, вы не сталкивались с такой информацией. Или, возможно, ваше прошлое включает в себя погружение в среду, которая была громогласна против базы данных (например, «эти администраторы баз данных - идиоты - мы мало, мы выбрали несколько стропальщиков кода java / c #, которые спасут день»), и в этом случае вы можете быть категорически против к мистическим болтовням некоторых двебов, говорящих вам, что ФК (и ограничения, которые они могут подразумевать) действительно важны, если вы просто послушаете.
В детстве всех учили, что чистить зубы важно. Можете ли вы обойтись без этого? Конечно, но где-то внизу у вас будет меньше доступных зубов, чем если бы вы чистили зубы после каждого приема пищи. Если бы мамы и папы были достаточно ответственны, чтобы охватить дизайн базы данных, а также гигиену полости рта, у нас не было бы этого разговора. :-)
источник
Я уверен, что есть много приложений, где вы можете сойти с рук, но это не лучшая идея. Вы не всегда можете рассчитывать на то, что ваше приложение будет правильно управлять базой данных, и, честно говоря, управление базой данных не должно вызывать особой озабоченности вашего приложения.
Если вы используете реляционную базу данных, то, похоже, в ней должны быть определены некоторые отношения . К сожалению, такое отношение (вам не нужны внешние ключи), похоже, поддерживается многими разработчиками приложений, которые предпочитают не беспокоиться о таких глупых вещах, как целостность данных (но это необходимо, потому что в их компаниях нет специализированных разработчиков баз данных). Обычно в базах данных, составленных этими типами, вам просто повезло, что у вас есть первичные ключи;)
источник
Внешние ключи необходимы для любой модели реляционной базы данных.
источник
Я всегда ими пользуюсь, но потом делаю базы данных для финансовых систем. База данных является важной частью приложения. Если данные в финансовой базе данных не совсем точны, тогда действительно не имеет значения, сколько усилий вы потратите на разработку кода / внешнего интерфейса. Ты просто тратишь свое время.
Существует также тот факт, что несколько систем обычно должны взаимодействовать напрямую с базой данных - от других систем, которые просто считывают данные (Crystal Reports), до систем, которые вставляют данные (необязательно с использованием разработанного мной API; это может быть написано тупой менеджер, который только что обнаружил VBScript и имеет пароль SA для блока SQL). Если база данных не настолько идиотобезопасна, как может быть, пока, пока, база данных.
Если ваши данные важны, тогда да, используйте внешние ключи, создайте набор хранимых процедур для взаимодействия с данными и создайте самую жесткую БД, какую только сможете. Если ваши данные не важны, почему вы делаете базу данных для начала?
источник
Обновление : теперь я всегда использую внешние ключи. Мой ответ на возражение «они усложняют тестирование» - «напишите свои модульные тесты, чтобы им вообще не нужна база данных. Любые тесты, использующие базу данных, должны использовать ее должным образом, включая внешние ключи. Если установка болезненная, найти менее болезненный способ сделать настройку. "
Внешние ключи усложняют автоматизированное тестирование
Предположим, вы используете внешние ключи. Вы пишете автоматический тест, который говорит: «Когда я обновляю финансовый счет, он должен сохранить запись транзакции». В этом тесте вас интересуют только две таблицы:
accounts
иtransactions
.Тем
accounts
не менее, имеет внешний ключ дляcontracts
, иcontracts
имеет fk toclients
, иclients
имеет fk tocities
, иcities
имеет fk tostates
.Теперь база данных не позволит вам запустить тест без настройки данных в четырех таблицах, которые не имеют отношения к вашему тесту .
На это есть как минимум две возможные перспективы:
Также возможно временно отключить проверку внешних ключей во время выполнения тестов. MySQL, по крайней мере, поддерживает это .
источник
«Они могут сделать удаление записей более громоздким - вы не можете удалить« основную »запись, где есть записи в других таблицах, где внешние ключи нарушают это ограничение».
Важно помнить, что стандарт SQL определяет действия, которые предпринимаются при удалении или обновлении внешнего ключа. Те, о которых я знаю:
ON DELETE RESTRICT
- Предотвращает удаление любых строк в другой таблице, имеющих ключи в этом столбце. Это то, что Кен Рэй описал выше.ON DELETE CASCADE
- Если строка в другой таблице удалена, удалите все строки в этой таблице, которые ссылаются на нее.ON DELETE SET DEFAULT
- Если строка в другой таблице удалена, установите любые внешние ключи, ссылающиеся на нее, по умолчанию для столбца.ON DELETE SET NULL
- Если строка в другой таблице удалена, установите для любых внешних ключей, ссылающихся на нее в этой таблице, значение null.ON DELETE NO ACTION
- Этот внешний ключ только означает, что он является внешним ключом; а именно для использования в мапперах.Эти же действия относятся и к
ON UPDATE
.По умолчанию, кажется, зависит от того, какой SQL сервер вы используете.
источник
@imphasing - это именно тот тип мышления, который вызывает кошмары обслуживания.
Почему вы игнорируете декларативную ссылочную целостность, где данные могут быть гарантированно по меньшей мере непротиворечивыми, в пользу так называемого «принудительного применения программного обеспечения», которое в лучшем случае является слабой превентивной мерой.
источник
Есть одна веская причина не использовать их: если вы не понимаете их роль или то, как их использовать.
В неправильных ситуациях ограничения по внешнему ключу могут привести к аварийному воспроизведению водопадов. Если кто-то удалит неправильную запись, ее удаление может стать огромной задачей.
Кроме того, наоборот, когда вам нужно что-то удалить, если оно плохо спроектировано, ограничения могут вызвать всевозможные блокировки, которые мешают вам.
источник
Нет веских причин не использовать их ... если я не думаю, что пустые строки не имеют для вас большого значения.
источник
Более серьезный вопрос: вы бы поехали с завязанными глазами? Вот как это происходит, если вы разрабатываете систему без ссылочных ограничений. Помните, что меняются бизнес-требования, изменения дизайна приложения, соответствующие логические предположения в коде, сама логика может быть реорганизована и т. Д. В целом, ограничения в базах данных устанавливаются в соответствии с современными логическими предположениями, которые кажутся правильными для определенного набора логических утверждений и предположений.
На протяжении жизненного цикла приложения проверка ссылок и данных ограничивает сбор данных полиции через приложение, особенно когда новые требования приводят к изменениям логического приложения.
Что касается предмета этого списка - внешний ключ сам по себе не «повышает производительность» и не «значительно снижает производительность» с точки зрения системы обработки транзакций в реальном времени. Однако в «пакетной» системе ВЫСОКОГО объема используется совокупная стоимость проверки ограничений. Итак, вот разница между процессом в реальном времени и процессом пакетной обработки; пакетная обработка - когда совокупные затраты, связанные с проверками ограничений, для последовательно обработанной партии представляют собой снижение производительности.
В хорошо спроектированной системе проверки непротиворечивости данных будут выполняться «до» обработки пакета (тем не менее, здесь также есть стоимость); поэтому проверки ограничений внешнего ключа не требуются во время загрузки. Фактически все ограничения, включая внешний ключ, должны быть временно отключены до обработки пакета.
QUERY PERFORMANCE - если таблицы объединяются по внешним ключам, следует учитывать тот факт, что столбцы внешнего ключа НЕ УКАЗАНЫ (хотя соответствующий первичный ключ индексируется по определению). Индексирование внешнего ключа, в этом отношении, индексация любого ключа и присоединение таблиц к индексированным помогает повысить производительность, а не присоединение к неиндексированному ключу с ограничением внешнего ключа.
Смена темы : если база данных просто поддерживает отображение / отображение контента сайта и т. Д. И запись кликов, то для таких целей база данных с полными ограничениями для всех таблиц излишне убивает. Подумай об этом. Большинство веб-сайтов даже не используют базу данных для таких целей. Для аналогичных требований, когда данные просто записываются и не имеют ссылки, скажем, используйте базу данных в памяти, которая не имеет ограничений. Это не означает, что нет модели данных, да, логическая модель, но нет физической модели данных.
источник
Дополнительная причина для использования внешних ключей: - Позволяет большее повторное использование базы данных
Дополнительная причина НЕ использовать иностранные ключи: - Вы пытаетесь заблокировать клиента в своем инструменте, уменьшая повторное использование.
источник
Исходя из моего опыта, всегда лучше избегать использования FKs в критических приложениях базы данных. Я бы не стал спорить с парнями, которые говорят, что FK - это хорошая практика, но она не практична, когда база данных огромна и имеет огромные операции CRUD / сек. Я могу поделиться без имен ... один из крупнейших инвестиционных банков не имеет ни одного ФК в базах данных. Эти ограничения обрабатываются программистами при создании приложений с использованием БД. Основная причина в том, что когда делается новый CRUD, он должен воздействовать на несколько таблиц и проверять каждую вставку / обновление, хотя это не будет большой проблемой для запросов, затрагивающих отдельные строки, но создает огромную задержку при работе с пакетная обработка, которую любой крупный банк должен выполнять как повседневные задачи.
Лучше избегать ФК, но его риск должен быть решен программистами.
источник
«Перед добавлением записи убедитесь, что соответствующая запись существует в другой таблице» - это бизнес-логика.
Вот несколько причин, по которым вы не хотите этого в базе данных:
Если бизнес-правила меняются, вы должны изменить базу данных. В большинстве случаев базе данных потребуется пересоздать индекс, а на больших таблицах это происходит медленно. (Изменение правил включает: разрешать гостям публиковать сообщения или разрешать пользователям удалять свою учетную запись, несмотря на то, что они оставили комментарии и т. Д.).
Изменение базы данных не так просто, как развертывание исправления программного обеспечения путем внесения изменений в производственный репозиторий. Мы хотим максимально избежать изменения структуры базы данных. Чем больше бизнес-логики в базе данных, тем больше вы увеличиваете вероятность необходимости изменения баз данных (и запуска реиндексации).
TDD. В модульных тестах вы можете заменить базу данных на макеты и проверить функциональность. Если у вас есть какая-либо бизнес-логика в вашей базе данных, вы не выполняете полные тесты и вам необходимо либо провести тестирование с базой данных, либо скопировать бизнес-логику в коде для целей тестирования, дублируя логику и увеличивая вероятность того, что логика не работает в так же.
Повторное использование вашей логики с различными источниками данных. Если в базе данных нет логики, мое приложение может создавать объекты из записей из базы данных, создавать их из веб-службы, файла json или любого другого источника. Мне просто нужно поменять реализацию картографа данных и использовать всю мою бизнес-логику с любым источником. Если в базе данных есть логика, это невозможно, и вам необходимо реализовать логику на уровне отображения данных или в бизнес-логике. В любом случае, вам нужны эти проверки в вашем коде. Если в базе данных нет логики, я могу развернуть приложение в разных местах, используя разные реализации базы данных или плоских файлов.
источник
Я согласен с предыдущими ответами в том, что они полезны для обеспечения согласованности данных. Однако несколько недель назад Джефф Этвуд опубликовал интересный пост, в котором обсуждались плюсы и минусы нормализованных и непротиворечивых данных.
В нескольких словах денормализованная база данных может быть быстрее при обработке огромных объемов данных; и вы можете не заботиться о точной согласованности в зависимости от приложения, но это заставляет вас быть намного более осторожным при работе с данными, поскольку БД не будет.
источник
База данных Clarify является примером коммерческой базы данных, которая не имеет первичных или внешних ключей.
http://www.geekinterview.com/question_details/18869
Самое смешное, что техническая документация очень подробно объясняет, как связаны таблицы, какие столбцы использовать для их объединения и т. Д.
Другими словами, они могли бы присоединиться к таблицам с явными объявлениями (DRI), но решили не делать этого .
Следовательно, база данных Clarify полна несоответствий и неэффективна.
Но я полагаю, что это упростило работу разработчиков, не требуя написания кода, чтобы справиться с ссылочной целостностью, такой как проверка связанных строк перед удалением, добавлением.
И это, я думаю, является основным преимуществом отсутствия ограничений внешнего ключа в реляционной базе данных. Это облегчает разработку, по крайней мере, с точки зрения дьявольской заботы.
источник
Я знаю только базы данных Oracle, никаких других, и могу сказать, что внешние ключи необходимы для поддержания целостности данных. Перед вставкой данных необходимо создать структуру данных и сделать ее правильной. Когда это сделано - и, таким образом, все первичные и внешние ключи созданы - работа завершена!
Значение: осиротевшие строки? Нет. Никогда не видел этого в моей жизни. Если только плохой программист не забыл внешний ключ или не реализовал его на другом уровне. И то, и другое - в контексте Oracle - огромные ошибки, которые приведут к дублированию данных, потерям данных и, следовательно, к повреждению данных. Я не могу представить базу данных без применения ФК. Это похоже на хаос для меня. Это немного похоже на систему разрешений Unix: представьте, что все - root. Подумай о хаосе.
Внешние ключи необходимы, как и первичные ключи. Это все равно что сказать: что если мы удалим первичные ключи? Ну, полный хаос случится. Это то что. Вы не можете перенести ответственность первичного или внешнего ключа на уровень программирования, он должен быть на уровне данных.
Недостатки? Да, конечно ! Потому что при вставке будет происходить намного больше проверок. Но, если целостность данных важнее производительности, это не сложно. Проблема с производительностью в Oracle больше связана с индексами, которые поставляются с PK и FK.
источник
Они могут сделать удаление записей более громоздким - вы не можете удалить «основную» запись, где есть записи в других таблицах, где внешние ключи нарушают это ограничение. Вы можете использовать триггеры для каскадного удаления.
Если вы выбрали свой первичный ключ неразумно, то изменение этого значения становится еще более сложным. Например, если у меня в качестве имени человека указан PK моей таблицы «customer», и я сделаю этот ключ FK в таблице «orders», если клиент хочет изменить свое имя, то это королевская боль ... но это просто плохой дизайн базы данных.
Я полагаю, что преимущества использования ключей fireign перевешивают любые предполагаемые недостатки.
источник
Проверка ограничений внешнего ключа требует некоторого процессорного времени, поэтому некоторые люди опускают внешние ключи, чтобы получить дополнительную производительность.
источник
Я также слышал этот аргумент - от людей, которые забыли поставить индекс для своих внешних ключей, а затем пожаловались, что некоторые операции выполняются медленно (поскольку проверка ограничений может использовать любой индекс). Итак, подведем итоги: нет веских причин не использовать внешние ключи. Все современные базы данных поддерживают каскадное удаление, так что ...
источник
Аргумент, который я услышал, состоит в том, что у переднего конца должны быть эти бизнес-правила. Внешние ключи «добавляют ненужные накладные расходы», когда вы не должны допускать никаких вставок, которые в первую очередь нарушают ваши ограничения. Согласен ли я с этим? Нет, но это то, что я всегда слышал.
РЕДАКТИРОВАТЬ: я думаю, что он имел в виду ограничения внешнего ключа , а не внешние ключи в качестве концепции.
источник
Для меня, если вы хотите следовать стандартам ACID , очень важно иметь внешние ключи для обеспечения ссылочной целостности.
источник
Я должен повторить большинство комментариев здесь. Внешние ключи являются необходимыми элементами для обеспечения целостности ваших данных. Различные опции для ON DELETE и ON UPDATE позволят вам обойти некоторые «падения», которые люди упоминают здесь относительно их использования.
Я обнаружил, что в 99% всех моих проектов у меня есть FK для обеспечения целостности данных, однако есть те редкие случаи, когда у меня есть клиенты, которые ДОЛЖНЫ хранить свои старые данные, независимо от того, насколько они плохие .... но потом я трачу много времени на написание кода, который в любом случае получает только действительные данные, так что это становится бессмысленным.
источник
Как насчет ремонтопригодности и постоянства в жизненных циклах приложений? Большинство данных имеют более длительный срок службы, чем приложения, которые их используют. Отношения и целостность данных слишком важны, чтобы оставлять надежду на то, что следующая команда разработчиков сделает это прямо в коде приложения. Если вы не работали с БД с грязными данными, которые не уважают естественные отношения, вы это сделаете. Важность целостности данных станет очень ясной.
источник
Я также считаю, что внешние ключи необходимы в большинстве баз данных. Единственный недостаток (помимо снижения производительности, связанного с принудительной согласованностью) заключается в том, что наличие внешнего ключа позволяет людям писать код, предполагающий наличие функционального внешнего ключа. Это никогда не должно быть позволено.
Например, я видел, как люди писали код, который вставлял в ссылочную таблицу, а затем пытался вставить в ссылочную таблицу, не проверяя, была ли успешной первая вставка. Если внешний ключ удаляется позднее, это приводит к несогласованности базы данных.
У вас также нет возможности принять определенное поведение при обновлении или удалении. Вам все еще нужно написать свой код, чтобы делать то, что вы хотите, независимо от того, присутствует ли внешний ключ. Если вы предполагаете, что удаления каскадируются, когда это не так, ваши удаления будут неудачными. Если вы предполагаете, что обновления в ссылочных столбцах распространяются на ссылочные строки, когда их нет, ваши обновления завершатся неудачно. В целях написания кода у вас могут не быть этих функций.
Если эти функции включены, то ваш код все равно будет эмулировать их, и вы потеряете немного производительности.
Итак, резюме .... Внешние ключи необходимы, если вам нужна согласованная база данных. Внешние ключи никогда не должны присутствовать или функционировать в коде, который вы пишете.
источник
Я повторяю ответ Дмитрия - очень хорошо сказано.
Для тех, кого беспокоит нехватка производительности, которую часто приносят FK, есть способ (в Oracle) получить преимущество оптимизатора запросов от ограничения FK без дополнительных затрат на проверку ограничения во время вставки, удаления или обновления. То есть создать ограничение FK с атрибутами RELY DISABLE NOVALIDATE. Это означает, что оптимизатор запросов ПРИНИМАЕТ, что ограничение было применено при построении запросов, при этом база данных фактически не применяла ограничение Вы должны быть очень осторожны, чтобы взять на себя ответственность, когда вы заполняете таблицу с помощью ограничения FK, как это, чтобы быть абсолютно уверенным, что у вас нет данных в ваших столбцах FK, которые нарушают ограничение, как если бы вы это сделали мог получить ненадежные результаты из запросов, включающих таблицу, к которой относится это ограничение FK.
Я обычно использую эту стратегию в некоторых таблицах в моей схеме витрины данных, но не в моей интегрированной промежуточной схеме. Я удостоверяюсь, что таблицы, из которых я копирую данные, уже имеют такое же ограничение, или процедура ETL применяет это ограничение.
источник
Многие из отвечающих здесь людей слишком зациклены на важности ссылочной целостности, реализуемой посредством ссылочных ограничений. Работа с большими базами данных с ссылочной целостностью просто неэффективна. Oracle выглядит особенно плохо при каскадном удалении. Мое эмпирическое правило заключается в том, что приложения никогда не должны обновлять базу данных напрямую и должны выполняться через хранимую процедуру. Это сохраняет базу кода внутри базы данных и означает, что база данных сохраняет свою целостность.
Когда многие приложения могут получать доступ к базе данных, проблемы возникают из-за ограничений ссылочной целостности, но это зависит от контроля.
Существует также более широкая проблема, заключающаяся в том, что у разработчиков приложений могут быть очень разные требования, с которыми разработчики баз данных могут не обязательно быть знакомы с ними.
источник
Если вы абсолютно уверены, что одна базовая система баз данных не изменится в будущем, я бы использовал внешние ключи для обеспечения целостности данных.
Но вот еще одна очень хорошая причина из реальной жизни вообще не использовать внешние ключи:
Вы разрабатываете продукт, который должен поддерживать различные системы баз данных.
Если вы работаете с Entity Framework, который может подключаться ко многим различным системам баз данных, вы можете также захотеть поддерживать бесплатные серверные базы данных с открытым исходным кодом. Не все эти базы данных могут поддерживать ваши правила внешнего ключа (обновление, удаление строк ...).
Это может привести к различным проблемам:
1.) Вы можете столкнуться с ошибками при создании или обновлении структуры базы данных. Возможно, будут только тихие ошибки, потому что ваши внешние ключи просто игнорируются системой базы данных.
2.) Если вы полагаетесь на внешние ключи, вы, вероятно, будете меньше или вообще не проверять целостность данных в своей бизнес-логике. Теперь, если новая система баз данных не поддерживает эти правила внешнего ключа или просто ведет себя по-другому, вы должны переписать свою бизнес-логику.
Вы можете спросить: кому нужны разные системы баз данных? Ну, не каждый может позволить себе или хочет полноценный SQL-сервер на своей машине. Это программное обеспечение, которое необходимо поддерживать. Другие уже вложили время и деньги в какую-то другую систему БД. Бессерверная база данных отлично подходит для небольших клиентов только на одном компьютере.
Никто не знает, как ведут себя все эти системы БД, но ваша бизнес-логика с проверками целостности всегда остается неизменной.
источник
Я всегда думал, что было лениво не использовать их. Меня учили, это всегда должно быть сделано. Но тогда я не слушал дискуссию Джоэла. Возможно, у него была веская причина, я не знаю.
источник
Однажды, когда FK может вызвать у вас проблему, это когда у вас есть исторические данные, которые ссылаются на ключ (в таблице поиска), даже если вы больше не хотите, чтобы ключ был доступен.
Очевидно, что решение состоит в том, чтобы лучше спроектировать вещи заранее, но я думаю о реальных ситуациях, когда вы не всегда можете полностью контролировать решение.
Например: возможно, у вас есть справочная таблица, в
customer_type
которой перечислены различные типы клиентов - допустим, вам нужно удалить определенный тип клиентов, но (из-за ограничений бизнеса) не удается обновить программное обеспечение клиента, и никто не обращал внимания на эту ситуацию При разработке программного обеспечения тот факт, что он является внешним ключом в какой-то другой таблице, может помешать вам удалить строку, даже если вы знаете исторические данные, которые ссылаются на нее, не имеет значения.После нескольких сожжений вы, вероятно, откажетесь от навязывания отношений с БД.
(Я не говорю, что это хорошо, просто приводя причину, по которой вы можете решить избегать FKs и db-ограничений вообще)
источник