По моему опыту, многие из проектов, которые я читал в прошлом, не имели определений отношений в базе данных, вместо этого они определяли их только в исходном коде. Поэтому мне интересно, каковы преимущества / недостатки определения отношений между таблицами в базе данных и в исходном коде? И более широкий вопрос касается других дополнительных функций в современных базах данных, таких как каскад, триггеры, процедуры ... В моих мыслях есть несколько моментов:
В базе данных:
Правильные данные из дизайна. Предотвратите ошибки приложения, которые могут вызвать неправильные данные.
Сократите количество обращений к сети в приложении при вставке / обновлении данных, поскольку приложение должно выполнить больше запросов для проверки целостности данных.
В исходном коде:
Более гибкий.
Лучше при масштабировании на несколько баз данных, так как иногда связь может быть кросс-базой данных.
Больше контроля над целостностью данных. База данных не должна проверять каждый раз, когда приложение изменяет данные (сложность может быть O (n) или O (n log n) (?)). Вместо этого он делегирован приложению. И я думаю, что обработка целостности данных в приложении приведет к более подробным сообщениям об ошибках, чем при использовании базы данных. Например: когда вы создаете сервер API, если вы определяете отношения в базе данных, и что-то идет не так (как ссылка на сущность не существует), вы получите исключение SQL с сообщением. Простым способом будет вернуть клиенту 500, что есть «Внутренняя ошибка сервера», и клиент не будет знать, что происходит не так. Или сервер может проанализировать сообщение, чтобы выяснить, в чем дело, что, на мой взгляд, является уродливым и подверженным ошибкам способом. Если вы позволите приложению справиться с этим,
Что-нибудь еще?
Изменить: как указывает Килиан, моя точка зрения о производительности и целостности данных очень ошибочна. Так что я отредактировал, чтобы исправить мою точку зрения там. Я полностью понимаю, что разрешение базы данных обрабатывать это будет более эффективным и надежным подходом. Пожалуйста, проверьте обновленный вопрос и расскажите о нем.
Редактировать: спасибо всем. Все ответы, которые я получил, указывают на то, что ограничения / отношения должны быть определены в базе данных. :). У меня есть еще один вопрос, так как он выходит за рамки этого вопроса, я просто разместил его как отдельный вопрос: Обработка ошибок базы данных для сервера API . Пожалуйста, оставьте некоторые идеи.
Ответы:
TL; DR: ограничения отношений должны идти в базу данных.
Ваше приложение недостаточно велико.
Вы действительно правы, что для обеспечения взаимосвязей между базами данных может потребоваться применение их в приложении.
Однако я хотел бы отметить, что вы должны сначала проверить документацию программного обеспечения базы данных, которое вы используете, и проверить существующие предложения продуктов. Например, есть предложения кластеризации поверх Postgres и MySQL.
И даже если вы в конечном итоге нужно иметь некоторую проверку в применении, не выплеснуть ребенка вместе с водой . В конце концов, чем меньше вы должны делать, тем лучше для вас.
Наконец, если вы беспокоитесь о будущих проблемах масштабируемости, я боюсь, что ваше приложение должно будет претерпеть значительные изменения, прежде чем оно сможет масштабироваться в любом случае. Как правило, каждый раз, когда вы растете в 10 раз, вы должны переделывать дизайн ... так что давайте не будем тратить слишком много денег на то, чтобы не предвидеть проблемы масштабируемости, а вместо этого использовать деньги, чтобы фактически достичь точки, где у вас есть эти проблемы.
Ваша заявка не является правильной.
Какова вероятность того, что используемая вами база данных имеет ошибочную реализацию проверки по сравнению с вероятностью того, что ваше приложение имеет ошибочную реализацию проверки?
И какой из них вы меняете чаще всего?
Я бы поставил на правильность базы данных в любое время .
Ваши разработчики не думают, что распределены достаточно.
Красный флаг ! 1
Если вы думаете:
затем вы потерпели неудачу в самой основной проблеме параллелизма: другой процесс / поток может добавлять запись по ходу работы.
Если вы думаете:
затем вы не смогли учесть MVCC: представление базы данных, которая у вас есть, является моментальным снимком на момент начала транзакции; он не показывает все обновления, которые происходят, и, возможно, даже не зафиксированы.
Поддержание ограничений для нескольких сессий - это действительно сложная проблема, и мы рады, что она решена в вашей базе данных.
1 Если ваша база данных правильно не реализует свойство Serializable; но немногие на самом деле делают.
Прошлой:
Не анализируйте сообщения об ошибках , если вы используете какую-либо производственную базу данных, она должна возвращать структурированные ошибки. У вас будет хотя бы некоторый код ошибки, чтобы указать, что, возможно, не так, и на основе этого кода вы сможете создать подходящее сообщение об ошибке.
Обратите внимание, что в большинстве случаев кода достаточно: если у вас есть код ошибки, сообщающий, что ссылочный внешний ключ не существует, то, вероятно, эта таблица имеет только один внешний ключ, поэтому вы знаете в коде, в чем проблема ,
Кроме того, и давайте будем честными здесь, в большинстве случаев вы не будете обрабатывать ошибки, которые все равно изящны. Просто потому, что их так много, и вы не сможете отчитаться за них всех ...
... который просто связан с точкой правильности выше. Каждый раз, когда вы видите «500: Внутренняя ошибка сервера», потому что ограничение базы данных сработало и не было обработано, это означает, что база данных спасла вас, поскольку вы просто забыли обработать ее в коде.
источник
Это глубоко ошибочный момент. Базы данных были созданы именно для этой цели. Если вам нужны проверки целостности данных (и если вы думаете, что они вам не нужны, вы, вероятно, ошибаетесь), то разрешение обработать их базой данных почти наверняка более эффективно и менее подвержено ошибкам, чем в логике приложения.
источник
Ограничения должны лежать в вашей базе данных, поскольку (при всем желании) ваше приложение не будет единственным, кто когда-либо получит доступ к этой базе данных.
В какой-то момент в базе данных может потребоваться исправление по сценарию, или вам может потребоваться перенести данные из одной таблицы в другую при развертывании.
Кроме того, вы можете получить другие требования, например: «Большому клиенту X действительно нужен этот лист данных Excel, импортированный в нашу базу данных приложений сегодня днем», где вы не сможете позволить себе адаптировать код приложения в соответствии с выполнением грязного сценария SQL. во время.
Это где целостность уровня базы данных спасет ваш бекон.
Кроме того, представьте себе разработчика, который берет на себя вашу роль в этой компании после вашего ухода, а затем ему поручено внести изменения в базу данных.
Будет ли он вас ненавидеть, если в базе данных нет ограничений FK, чтобы он мог сказать, какие отношения у таблицы, прежде чем он ее изменит? ( Подсказка, ответ - да )
источник
Вы должны иметь отношения в базе данных.
Как отмечается в другом ответе, производительность проверки ограничений будет гораздо лучше внутри этой базы данных, чем внутри вашего приложения. Проверка ограничений базы данных - одна из тех вещей, с которыми хорошо справляются базы данных.
Если вам когда-нибудь понадобится дополнительная гибкость - например, ваши отмеченные перекрестные ссылки на базы данных - тогда вы можете снять ограничения преднамеренно и с вниманием. Наличие согласованности в вашей базе данных означает, что у вас есть возможность изменить эти ограничения и уверенность в ссылочной целостности.
источник
Можете ли вы позволить себе писать и тестировать код, обеспечивающий ссылочную целостность, когда у вас есть код для решения проблем домена?
источник
Если вы не проверяете целостность данных, ограничения, взаимосвязи и т. Д. На уровне базы данных, это означает, что любому, имеющему доступ к производственной базе данных (через любой другой клиент, включая инструмент доступа к БД), будет намного проще испортить ваши данные.
Хорошей практикой является обеспечение как можно более строгой целостности данных на уровне базы данных. Поверьте мне, это избавит вас от огромных головных болей с течением времени в любой нетривиальной системе. Вы также быстрее обнаружите ошибки логики приложения, а также ошибки и несоответствия бизнес-требований, если тщательно обдумать это.
Как примечание к этому, проектируйте свою базу данных так, чтобы она была максимально нормализована и атомарна. Никаких «божьих» столов. Потратьте много усилий, чтобы сделать вашу базу данных максимально простой, в идеале с множеством небольших таблиц, которые по отдельности очень хорошо определены, с единственной ответственностью и тщательно проверены по всем столбцам. База данных является последним хранителем вашей целостности данных. Он представляет собой крепость замка.
источник
Большинство людей по сути говорят: «Да, в общем, вы всегда должны определять отношения в базе данных». Но если бы дисциплины в области компьютерных наук были такими простыми, нас называли бы «Читатели программного обеспечения» вместо «Инженеры-программисты». Я действительно согласен с тем, что ограничения должны быть в базе данных, если только нет веской причины, по которой они не должны этого делать, поэтому позвольте мне привести пару причин, которые могут считаться хорошими в определенных ситуациях:
Дубликат кода
Иногда определенное количество функциональности, которая может быть обработана базой данных, естественно, существует в коде приложения. Если добавление чего-либо вроде ограничений в базу данных было бы излишним, возможно, лучше не дублировать функциональность, потому что вы нарушаете принципы DRY, и вы можете усугубить манипулирование синхронизацией базы данных и кода приложения.
усилие
Если ваша база данных уже делает то, что ей нужно, без использования расширенных функций, вы, возможно, захотите оценить, куда следует направить свое время, деньги и усилия. Если добавление ограничений предотвратит катастрофический сбой и, таким образом, сэкономит вашей компании много денег, то это, вероятно, того стоит. Если вы добавляете ограничения, которые должны соблюдаться, но которые гарантированно никогда не будут нарушены, вы теряете время и загрязняете свою базу кода. Гарантированное - это оперативное слово здесь.
КПД
Обычно это не веская причина, но в некоторых случаях у вас могут быть определенные требования к производительности. Если код приложения может реализовать определенные функции быстрее, чем база данных, и вам нужна дополнительная производительность, вам может потребоваться реализовать эту функцию в коде приложения.
контроль
Несколько связано с эффективностью. Иногда вам нужен чрезвычайно точный контроль над тем, как реализована функция, а иногда, когда база данных обрабатывает ее, она скрывает ее за черным ящиком, который вам нужно открыть.
Закрытие пунктов
Последнее, что я скажу, это то, что вы будете знать, не стоит ли размещать эту функциональность в базе данных. Если вы не уверены, вам, вероятно, лучше использовать функции базы данных, потому что они обычно работают очень хорошо.
источник
Как всегда, ответов много. Для меня я нашел простое правило (хорошо, оно работает только для модельно-ориентированного подхода). Обычно я фокусируюсь только на разных слоях приложений.
Если модель состоит из нескольких сущностей и существуют зависимости между сущностями, уровень постоянства должен отражать эти зависимости со своими возможностями. Поэтому, если вы используете СУРБД, вам также следует использовать внешние ключи. Причина проста. Таким образом, данные всегда действительны структурно.
Любой экземпляр, выполняющий работу на этом слое устойчивости, может на него положиться. Я предполагаю, что вы инкапсулируете этот слой через интерфейс (сервис). Итак, вот момент, когда дизайн заканчивается и начинается реальный мир.
Глядя на ваши точки, особенно ссылки на базы данных . В этом случае, да, должна быть ссылка, реализованная не в самой СУБД, а в службе. Но прежде чем идти по этому пути, не лучше ли обдумать это уже во время разработки?
Значит, если я уже знаю, что есть детали, которые нужно хранить в другой БД, тогда я могу поместить их уже там и определить как отдельную модель. Правильно?
Вы также указываете, что реализация этого в коде более гибкая . Правильно, но разве это не похоже на то, что вы имеете дело с неполным дизайном? Спросите себя, зачем вам больше гибкости?
Проблема с производительностью, связанная с проверками целостности в БД , не является реальной. СУБД может проверять такие вещи намного быстрее, чем любая ваша реализация. Почему? Что ж, вам приходится иметь дело со сбоем средств массовой информации, а RDBMS - нет. И он может оптимизировать такие проверки, используя свою статистику также
Итак, вы видите, все это возвращается к дизайну. Конечно, вы можете сказать сейчас, но что, если появляется неизвестное требование, меняющее правила игры? Да, это может произойти, но такие изменения должны быть разработаны и спланированы так же. ; О)
источник
У вас есть очень хорошие ответы, но есть еще несколько моментов
Целостность данных - это то, для чего предназначена база данных
Выполнение правильного параллелизма типа удаления FK на уровне приложения было бы ужасным
Экспертиза в целостности данных с DBA
На уровне программы вы вставляете, обновляете, массово обновляете, массово вставляете, массово удаляете ...
Тонкий клиент, толстый клиент, мобильный клиент ....
Целостность данных не является компетенцией программиста - много дублирующегося кода, и кто-то будет путаться это до
Скажем, вас взломали - у вас проблемы в любом случае, но хакер может нанести большой ущерб через маленькую дыру, если в базе данных нет защиты целостности
Возможно, вам придется манипулировать данными напрямую через SQL или TSQL.
Никто не помнит все правила данных
источник
Ваш вопрос не имеет смысла: если вы можете изменить базу данных, это код, если вы не можете изменить базу данных, вам придется создавать свои ограничения в другом месте.
База данных, которую вы можете изменить, содержит столько же кода, сколько любая строка ruby, javascript, c # или ada.
Вопрос о том, где наложить ограничения в вашей системе, должен сводиться к надежности, стоимости и простоте разработки.
источник
Здесь множество хороших ответов. Я добавлю, что если у вас есть приложение, написанное на языке Y, вы можете создать в Y код, похожий на ограничение базы данных. А затем кто-то захочет получить доступ к вашей базе данных с использованием языка Z, вам придется снова написать тот же код. Да поможет вам Бог, если реализации не совсем такие же. Или когда опытный бизнес-пользователь подключается к вашей базе данных с помощью Microsoft Access.
Мой опыт подсказывает мне, что когда люди не хотят использовать ограничения базы данных, это потому, что они на самом деле пытаются что-то сделать неправильно. Например, они пытаются выполнить массовую загрузку данных и хотят на некоторое время оставить ненулевые столбцы пустыми. Они намерены «исправить это позже», потому что ситуация, которая сделала ограничение ненулевым критическим, «не может произойти в этом случае». Другой пример может быть, когда они пытаются объединить два разных типа данных в одну таблицу.
Более опытные люди сделают шаг назад и найдут решение, которое не включает попытки обойти ограничение. Решением может быть просто ограничение, которое больше не является правильным, потому что бизнес, конечно, изменился.
источник