каким отношениям свойственны внешние ключи

Каким отношениям свойственны внешние ключи

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

При выделении связи выделяют главную или родительскую таблицу (primary key table / master table) и зависимую, дочернюю таблицу (foreign key table / child table). Дочерняя таблица зависит от родительской.

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

Связи между таблицами бывают следующих типов:

Один к одному (One to one)

Один к многим (One to many)

Многие ко многим (Many to many)

Связь один к одному

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

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

Например, таблица Users представляет пользователей и имеет следующие столбцы:

UserId (идентификатор, первичный ключ)

Name (имя пользователя)

И таблица Blogs представляет блоги пользователей и имеет следующие столбцы:

BlogId (идентификатор, первичный и внешний ключ)

Name (название блога)

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

каким отношениям свойственны внешние ключи

Связь один ко многим

К примеру, пусть будет таблица Articles, которая представляет статьи блога и которая имеет следующие столбцы:

ArticleId (идентификатор, первичный ключ)

BlogId (внешний ключ)

Title (название статьи)

В этом случае столбец BlogId из таблицы статей будет хранить значение из столбца BlogId из таблицы блогов.

каким отношениям свойственны внешние ключи

Связь многие ко многим

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

Например, в случае со статьями и тегами пусть будет таблица Tags, которая имеет два столбца:

TagId (идентификатор, первичный ключ)

Также пусть будет промежуточная таблица ArticleTags со следующими полями:

TagId (идентификатор, первичный и внешний ключ)

ArticleIdId (идентификатор, первичный и внешний ключ)

каким отношениям свойственны внешние ключи

Технически мы получим две связи один-ко-многим. Столбец TagId из таблицы ArticleTags будет ссылаться на столбец TagId из таблицы Tags. А столбец ArticleId из таблицы ArticleTags будет ссылаться на столбец ArticleId из таблицы Articles. То есть столбцы TagId и ArticleId в таблице ArticleTags представляют составной первичный ключ и одновременно являются внешними ключами для связи с таблицами Articles и Tags.

Ссылочная целостность данных

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

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

Аномалия вставки (insertion anomaly). Возникает при вставке строки в зависимую таблицу. В этом случае внешний ключ из зависимой таблицы не соответствует первичному ключу ни одной из строк из главной таблицы.

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

Аномалия удаления

Для решения аномалии удаления для внешнего ключа следует устанавливать одно из двух ограничений:

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

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

Аномалия вставки

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

Аномалии обновления

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

Источник

Создание связей по внешнему ключу

В этой статье описывается, как создать связи внешнего ключа в SQL Server с помощью среды SQL Server Management Studio или Transact-SQL. Связь создается между двумя таблицами, чтобы связать строки одной таблицы со строками другой.

Разрешения

Создание новой таблицы с внешним ключом требует разрешения CREATE TABLE в базе данных и разрешения ALTER на схему, в которой создается таблица.

Создание внешнего ключа в существующей таблице требует разрешения ALTER на таблицу.

Пределы и ограничения

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

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

Ограничения FOREIGN KEY могут ссылаться только на таблицы в пределах той же базы данных на том же сервере. Межбазовую ссылочную целостность необходимо реализовать посредством триггеров. Дополнительные сведения см. в статье об инструкции CREATE TRIGGER.

Ограничения FOREIGN KEY могут ссылаться на другие столбцы той же таблицы и считаются ссылками на себя.

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

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

Компонент Database Engine не имеет предопределенного ограничения на число ограничений FOREIGN KEY, которые могут содержаться в таблице, ссылающейся на другие таблицы. Компонент Database Engine также не ограничивает число ограничений FOREIGN KEY, принадлежащих другим таблицам, которые ссылаются на определенную таблицу. Но фактическое количество используемых ограничений FOREIGN KEY ограничивается конфигурацией оборудования, базы данных и приложения. Максимальное количество таблиц и столбцов, на которые может ссылаться таблица в качестве внешних ключей (исходящих ссылок), равно 253. SQL Server 2016 (13.x); и последующие версии увеличивает ограничение на количество других таблиц и столбцов, которые могут ссылаться на столбцы в одной таблице (входящие ссылки), с 253 до 10 000. (Требуется уровень совместимости не менее 130.) Увеличение имеет следующие ограничения:

Ограничения FOREIGN KEY не применяются к временным таблицам.

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

Создание связи по внешнему ключу в конструкторе таблиц

Использование SQL Server Management Studio

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

В меню конструктора таблиц выберите Связи.

В диалоговом окне Связи внешнего ключа нажмите кнопку Добавить.

Выберите нужную связь в списке Выбранные связи.

Выберите Спецификация таблиц и столбцов в сетке справа и нажмите кнопку с многоточием ( ) справа от свойства.

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

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

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

Источник

Связи, свойства навигации и внешние ключи

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

Связи в EF

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

каким отношениям свойственны внешние ключи

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

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

Рекомендуется включать в модель свойства, которые сопоставляются с внешними ключами в базе данных. Включение свойств внешних ключей позволяет создавать или изменять отношение, изменяя значение внешнего ключа для зависимого объекта. Сопоставление такого типа называется сопоставлением на основе внешнего ключа. Использование внешних ключей еще более важно при работе с отключенными сущностями. Обратите внимание, что при работе с 1-1 или 1 на-0. 1 связи нет отдельного внешнего ключевого столбца, свойство первичного ключа выступает в качестве внешнего ключа и всегда включается в модель.

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

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

каким отношениям свойственны внешние ключи

В следующем фрагменте кода показана та же модель, которая была создана с помощью Code First.

Настройка или сопоставление связей

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

Создание и изменение связей

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

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

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

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

Обратите внимание, что при обновлении (не просто добавлении) связи необходимо удалить старую связь после добавления новой.

Синхронизация изменений между внешними ключами и свойствами навигации

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

Загрузка связанных объектов

В Entity Framework свойства навигации обычно используются для загрузки сущностей, связанных с возвращаемой сущностью, с помощью заданной ассоциации. Дополнительные сведения см. в разделе Загрузка связанных объектов.

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

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

Управление параллелизмом

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

Дополнительные сведения см. в разделе Обработка конфликтов параллелизма.

Работа с перекрывающимися ключами

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

Источник

Что такое внешний ключ базы данных? Учебник для новичков

Эта статья написана Бриттни Паркер, писателем из Girls Write Tech, которая специализируется на написании технических материалов. Они стремятся побудить больше женщин-разработчиков делиться своими знаниями.

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

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

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

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

Что такое внешний ключ в базе данных?

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

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

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

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

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

каким отношениям свойственны внешние ключи

Скажем, у нас есть две таблицы с именами customerи order. Мы можем использовать внешний ключ для создания связи между ними. В ordersтаблице мы создаем ключ, который ссылается на клиента (т.е. CUSTOMER_ID) в другой таблице.

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

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

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

Ограничение FK

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

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

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

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

Внешний ключ против первичного ключа

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

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

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

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

Внешний ключ против составного ключа

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

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

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

Ссылочные действия внешнего ключа

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

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

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

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

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

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

Внешние ключи в SQL и MySQL

Давайте посмотрим на синтаксис с использованием SQL и MySQL. В следующем примере создается FOREIGN KEY в столбце «PersonID».

Узнайте больше о различных типах баз данных здесь

Следующий синтаксис позволяет нам назвать ограничение FOREIGN KEY:

Реальный пример SQL

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

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

В нашем примере мы изменяем наш DigitalAssetsи устанавливаем ActorIDстолбец как внешний ключ следующим образом:

Теперь, если мы добавим в DigitalAssetsтаблицу строку с идентификатором актера, которого нет в Actorsтаблице, появится сообщение об ошибке:

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

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

Источник

Взаимные блокировки и внешние ключи в SQL Server

каким отношениям свойственны внешние ключи

Введение

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

Будем использовать две таблицы: Department (Отдел) и Employee (Сотрудник). Столбец DepId в таблице Employee определен как внешний ключ, поэтому значения этого столбца будут проверяться на наличие соответствующих значений в столбце DepartmentId таблицы Department.

Что происходит за кулисами INSERT

Исследуем, какие операции выполняются при вставке данных в дочернюю таблицу (Employee).

Сначала вставим строку в родительскую таблицу (Department).

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

каким отношениям свойственны внешние ключи

Clustered Index Insert вставляет данные в кластерный индекс, а также обновляет некластерные индексы. Если внимательно посмотреть на этот оператор, то можно заметить, что для него не указано имя объекта. Причина этого как раз в том, что при вставке данных в кластерный индекс таблицы Employee, эти данные одновременно добавляются в некластерный индекс. Эти два индекса можно увидеть во всплывающей подсказке оператора Clustered Index Insert.

каким отношениям свойственны внешние ключи

Clustered Index Seek проверяет существование значения внешнего ключа в родительской таблице.

Nested Loops сравнивает вставленные значения внешних ключей со значениями, возвращаемые оператором Clustered Index Seek. В результате этого сравнения на выходе получается результат, который указывает, существует значение в родительской таблице или нет.

Assert оценивает результат оператора Nested Loops. Если Nested Loops возвращает NULL, то результат Assert будет ноль, и запрос вернет ошибку. В противном случае операция INSERT выполнится успешно.

каким отношениям свойственны внешние ключи

Взаимные блокировки

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

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

Следующие запросы выполним в разных сессиях. Сначала «Часть 1» первого запроса:

И первую часть второго запроса:

А теперь — вторые части запросов.

каким отношениям свойственны внешние ключи

В результате возникла взаимная блокировка.

Давайте проанализируем, что произошло:

Первая часть Запроса-1 открывает транзакцию и вставляет строку в таблицу Department. Страница данных Department блокируется монопольной блокировкой намерения (IX, intent exclusive lock), а вставленная строка — монопольной блокировкой (X, exclusive lock).

Первая часть Запроса-2 также открывает транзакцию и вставляет строку в Department. Страница данных таблицы Department блокируется монопольной блокировкой намерения (IX), а вставленная строка — монопольной блокировкой (X). На данный момент проблем с блокировками нет.

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

Запрос-2 блокируется при попытке прочитать строки, вставленные в Department в Запросе-1. У нас получилась взаимная блокировка.

Приведенный ниже граф взаимных блокировок иллюстрирует то, о чем мы говорили. Сессия 71 (Запрос-1) получил монопольную блокировку (X) для строк таблицы Employee и хочет получить разделяемую блокировку (S) для строк таблицы Department. В это же время сессия 51 получила эксклюзивную блокировку (X) для строк таблицы Department и хочет получить монопольную блокировку (X) для строк таблицы Employee. В результате между этими двумя сессиями возникает борьба за ресурсы, и SQL Server завершает одну из сессий.

каким отношениям свойственны внешние ключи

Устранение взаимных блокировок

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

каким отношениям свойственны внешние ключи

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

Мы можем изменить метод доступа к данным с помощью OPTION (LOOP JOIN). При использовании хинта LOOP JOIN, оптимизатор запросов SQL Server сгенерирует другой план выполнения и заменит оператор Merge Join оператором Nested Loops, а оператор Clustered Index Scan будет заменен оператором Clustered Index Seek. С помощью Clustered Index Seek доступ к данным родительской таблицы осуществляется напрямую, поэтому не требуется ждать заблокированных строк. С другой стороны, оператор Nested Loops выполняет построчное чтение, а Merge Join — одно последовательное чтение. Эти два изменения метода доступа к данным снижают вероятность блокировки запроса из-за наличия других блокировок.

каким отношениям свойственны внешние ключи

Row Count Spool используется для подсчета количества строк, возвращаемых оператором Clustered Index Seek, и передачи этой информации в оператор Nested Loops. Этот оператор используется оптимизатором запросов SQL Server для проверки существования строк, но не содержащихся в них данных.

Заключение

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

Материал подготовлен в рамках курса «MS SQL Server Developer». Всех желающих приглашаем на открытый урок «SQL Server и Docker». На открытом уроке мы поговорим о контейнерах, а также рассмотрим развертывание SQL Server в контейнерах.

Источник

Добавить комментарий

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