Ограничения целостности в реляционной базе данных - должны ли мы их игнорировать?


10

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

Рассматриваемой платформой является MySQL 5.x, и FOREIGN KEY не был установлен, даже отсутствуют некоторые ограничения PRIMARY KEY для соответствующих таблиц, что, по крайней мере для меня, нецелесообразно. Возможно, они правы, а я не прав, но у меня недостаточно аргументов для обсуждения этой ситуации.

Это был предпочтительный подход в течение трех лет. Я новичок в этой компании (всего один месяц), но, поскольку продукт «работает», есть нерешительность для улучшения базы данных; nevertheles, первое, что я заметил, это одна страница, которая загружается за 1 минуту (да, 60 секунд!).

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

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

Обычно обработка операций «CRUD» осуществляется на уровне кода прикладной программы; например, для того , чтобы удалить некоторые данные из, скажем, TableA:

  • необходимо сначала проверить на лету , есть ли связь между рядами TableAи TableB,
  • в случае, если упомянутое отношение «обнаружено», то программный код приложения не позволит УДАЛИТЬ соответствующие строки, но
  • если по какой-то причине код приложения не работает, то операция DELETE будет «успешной», независимо от того, есть ли какие-либо отношения в отношении задействованных строк и таблиц.

Вопрос

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


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


Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Пол Уайт 9

Ответы:


12

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

  • Нет, вы не должны игнорировать ограничения целостности данных .

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

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

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

Ограничения FOREIGN KEY, отношения данных и ссылочная целостность

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

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

Что касается обсуждаемой базы данных, можно сделать вывод, что соответствующие взаимосвязи были идентифицированы, поскольку вы упоминаете, что существует процедурная (и легко обходимая) попытка применить их извне средств СУБД посредством кода прикладной программы (который это предварительный реляционный подход), который в любом случае должен «касаться» базы данных, чтобы попытаться проверить целостность указанных взаимосвязей.

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

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

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

ПЕРВИЧНЫЕ КЛЮЧЕВЫЕ КЛЮЧИ И ПОСЛЕДСТВИЯ Дублирования строк

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

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

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

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

Этим способом:

  • Какую «версию» можно считать верной, надежной?
  • Какой из них точно отражает реальный мир?

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

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

Вот почему идентификация PRIMARY KEY (PK) и объявление соответствующего ограничения всегда должны выполняться разработчиком базы данных. Но следует также упомянуть, что таблица может иметь более одного столбца или комбинации столбцов, которые содержат значения, которые уникально идентифицируют каждую строку; как следствие, помимо установки ограничения PK (в идеале устанавливаемого как PRIMARY по прагматическим причинам), разработчик должен также объявить один или несколько ключей ALTERNATE (обычно определяемых с помощью одного или нескольких ограничений UNIQUE плюс NOT NULL), когда применяется (что является довольно часто).

Другим преимущественным свойством PK является то, что при «переносе» в другие таблицы для участия в единичных или составных FK они могут помочь обеспечить соотношение кардинальности отношений, существующих между данными. Все это, да, с помощью простых и эффективных декларативных настроек, обеспечиваемых СУБД.

(Текущие) ограничения CHECK и проверка одной строки

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

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

В связи с этим вам придется позаботиться об этом факторе с помощью других средств, например, ACID TRANSACTIONS , TRIGGERS или других методов в самой СУБД (см. Этот ответ по адресу @ ypercubeᵀᴹ для получения информации по этому вопросу), чтобы данные продолжали быть последовательным.

Ограничения ASSERTION: создание дополнительных бизнес-правил для нескольких строк и нескольких таблиц

Одним из аспектов, который по тем или иным причинам очень плохо поддерживается - если вообще - - различными СУБД SQL, включая MySQL, - это включение ограничений на несколько строк и нескольких таблиц декларативным способом - очевидно, помимо PK и FK.

Со своей стороны, стандарт SQL включает в себя ASSERTIONs за многие годы. Я не знаю, какие правила вашей бизнес-среды выиграют от этого подхода проверки на логическом уровне, но, как разработчик базы данных, я считаю, что было бы довольно удобно ограничивать данные одним или несколькими ОБЪЕКТАМИ, хотя я должен упомянуть это из С точки зрения разработчиков СУБД, этот первостепенный вид инструмента было трудно реализовать на физическом уровне абстракции.

Похоже, что поставщик и / или разработчики Oracle оценивают поддержку ASSERTION с 2016 года, и это сделало бы эту СУБД более подходящей с точки зрения отношений и, следовательно, более надежной и конкурентоспособной. Я предполагаю, что если (i) их потребители будут продолжать настаивать и (ii) Oracle преуспеет в реализации, то (iii) другие поставщики / сообщества СУБД также должны будут включить их, и их использование начнет распространяться. Конечно, это будет огромный прогресс в области управления базами данных, и, будучи одним из наиболее характерных инструментов, предусмотренных доктором Коддом, я лично надеюсь, что мы скоро это увидим.

Согласованность данных и процесс принятия решений

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

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

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

«Денормализация»

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

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

Таким образом, предполагая, что указанная таблица была на самом деле правильно нормализована, «денормализуя» ее (что, в отличие от формального значения слова, включает добавление к ней столбцов, которые принадлежат другим таблицам в объявлении и являются их частью). hoc fashion) может помочь, например, ускорить (на физическом уровне) обработку только одного или нескольких конкретных операторов SELECT, в то время как такой порядок действий может, в то же время, подорвать выполнение многих других связанных данных операции манипуляции (например, несколько операторов INSERT, UPDATE, DELETE и SELECT или их комбинации, заключенные в одну или несколько транзакций ACID).

Кроме того, денормализация (будь то формальная или неформальная) привела бы к аномалиям обновления / модификации, которые ухудшают согласованность базы данных, и эта проблема «может» решаться с помощью сложных, дорогостоящих и подверженных ошибкам процедур, когда все это можно предотвратить самое начало

Леса физического уровня, поддерживающие нормализованные и «денормализованные» таблицы

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

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

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

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

Функционирование рассматриваемой базы данных

Следующие параграфы вашего вопроса касаются скорости операций поиска данных:

[A] поскольку продукт «работает», существует нерешительность для улучшения базы данных; тем не менее, первое, что я заметил, это одна страница, которая загружается за 1 минуту (да, 60 секунд!).

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

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

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

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

  • Настройки INDEX могут потребовать улучшения.
  • Необходимо пересмотреть определения типов и размеров столбцов PK и FK (и я полностью согласен с @Rick James в отношении его соображений PK , поскольку составные ключи KEY, как правило, гораздо более эффективны, чем добавленные суррогаты в соответствующих случаях).
  • Дальнейшая (формальная, научно обоснованная) нормализация может помочь облегчить эти проблемы, учитывая тот факт, что при правильных обстоятельствах (т. Е. В правильно спроектированном RDB) соединения выполняются очень быстро .

Более того, да, как @TommCatt упоминает в своем ответе , иногда (логическое) переписывание запроса изменяет его (физический) план выполнения, ускоряя чтение / запись данных, что является фактором, который следует принимать во внимание.


1
Отличный ответ. Когда я рассматриваю производительность реализации, я всегда напоминаю себе, что команда разработчиков гораздо умнее, чем я, очень долго работал над этими проблемами. Реляционные базы данных находятся в центре самых огромных систем в мире (Facebook и Twitter, чтобы назвать несколько очевидных).
Ник Бедфорд

9

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

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

Ни при каких обстоятельствах не удаляйте FK из базы данных OLTP.

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

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

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

select <something> from <SomeView> where <whatever>;

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

Я действительно съеживаюсь, когда кто-то говорит: «потому что продукт« работает », есть нерешительность для улучшения базы данных». Если это "колебание" больше похоже на "не на мои часы, приятель!" тогда вы можете даже начать обновлять свое резюме. Ничто хорошее никогда не выйдет из такой среды, и вы будете нести ответственность за каждый будущий сбой, даже если вы часами лоббировали внесение изменений, которые предотвратили бы сбой. Вы услышите: «Сейчас не время для перемен» снова и снова. Правильно. Удачи.


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

2

Изменение заголовка меняет вопрос. FOREIGN KEYsявляются необязательными. Они делают:

  • ФК неявно создает INDEXв одной из таблиц. Такой индекс можно добавить вручную. (Так что FK не требуется для этого.)
  • ФК проверяет целостность. Это главная претензия ФК на славу. FK не требуется, поскольку ваше приложение может выполнить аналогичные проверки или решить, что проверка не нужна. Так...
  • Проверка целостности чего-то стоит в производительности; так что это замедляет обработку. (Обычно это не имеет большого значения.)
  • ФК делают не все, что хотят все; Этот форум изобилует вопросами «почему ФК не могут делать X». В частности, CHECKопция не действует.
  • ФК могут CASCADEвещи. (Лично я предпочитаю контролировать ситуацию и не предполагать, что ФК «поступит правильно».)

Итог для ФК: Некоторые люди настаивают на ФК; некоторые продукты прекрасно живут без них. Вам решать.

Избавиться от PRIMARY KEYInnoDB - большая ошибка. С другой стороны, избавление от суррогата AUTO_INCREMENTи использование «естественного» ПК, состоящего из одного (или более) столбца, часто является правильным решением. Простым, распространенным случаем является таблица сопоставления многие: многие, как обсуждалось здесь .

Исходя из личного опыта, я предлагаю, чтобы в 2/3 таблиц лучше использовать «естественный» вместо auto_inc PK.


1
Итак ... вы полагаетесь почти на идеальное приложение, потому что если разработчик допустит ошибку, DELETEнапример, и у вас нет ограничений на стороне БД, вы закончите потерю данных. Этот подход действителен, но требует интенсивного кода и хорошего тестирования, которого у них не было :)
ReynierPM

Удаление слишком много может произойти в приложении или с FK. Удаление слишком мало обычно становится очевидным. OTOH, я видел случаи, когда удаление слишком мало стоит затрат - подумайте о «нормализации», когда вещи редко удаляются. Дополнительные, неиспользованные ряды практически безвредны.
Рик Джеймс

Я видел один «хороший» случай отсутствия индексов на столе - промежуточная таблица для высокоскоростного приема. Он очень временный (поэтому InnoDB не нужен), и его нужно только полностью прочитать (следовательно, индексы не нужны).
Рик Джеймс

1
Обратите внимание на общую тему в моих разговорах: нет единого ответа; не один размер подходит всем.
Рик Джеймс

Если у вас таблицы длиной в тысячу строк; производительность не проблема. Если длина ваших таблиц составляет миллиард строк, необходимо тщательно изучить все «правила» о нормализации, PK, индексах, FK, UUID и т. Д. Иначе БД растает.
Рик Джеймс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.