Как вы обнаружили на своем exists
примере, SQL Server может использовать тот факт, что внешний ключ является доверенным при построении плана запроса.
Есть ли что-то еще, что я теряю при использовании NOCHECK?
Помимо того факта, что вы можете добавлять значения в столбец, которых там не должно быть, как ответил Ste Bov, у вас будет больше сценариев, в которых план запроса будет лучше, когда внешний ключ является доверенным.
Вот один пример с индексированным представлением .
У вас есть две таблицы с доверенным ограничением FK.
create table dbo.Country
(
CountryID int primary key,
Name varchar(50) not null
);
create table dbo.City
(
CityID int identity primary key,
Name varchar(50),
IsBig bit not null,
CountryID int not null
);
alter table dbo.City
add constraint FK_CountryID
foreign key (CountryID)
references dbo.Country(CountryID);
Существует не так много стран, но есть миллионы городов, и некоторые из них являются большими городами.
Пример данных:
-- Three countries
insert into dbo.Country(CountryID, Name) values
(1, 'Sweden'),
(2, 'Norway'),
(3, 'Denmark');
-- Five big cities
insert into dbo.City(Name, IsBig, CountryID) values
('Stockholm', 1, 1),
('Gothenburg', 1, 1),
('Malmoe', 1, 1),
('Oslo', 1, 2),
('Copenhagen', 1, 3);
-- 300 small cities
insert into dbo.City(Name, IsBig, CountryID)
select 'NoName', 0, Country.CountryID
from dbo.Country
cross apply (
select top(100) *
from sys.columns
) as T;
Наиболее часто выполняемые запросы в этом приложении связаны с определением количества крупных городов в каждой стране. Чтобы ускорить процесс, мы добавляем индексированное представление.
create view dbo.BigCityCount with schemabinding
as
select count_big(*) as BigCityCount,
City.CountryID,
Country.Name as CountryName
from dbo.City
inner join dbo.Country
on City.CountryID = Country.CountryID
where City.IsBig = 1
group by City.CountryID,
Country.Name;
go
create unique clustered index CX_BigCityCount
on dbo.BigCityCount(CountryID);
Через некоторое время появляется требование добавить новую страну
insert into dbo.Country(CountryID, Name) values(4, 'Finland');
План запроса для этой вставки не имеет сюрпризов.
Вставка кластерного индекса в Country
таблицу.
Теперь, если ваш внешний ключ не был доверенным
alter table dbo.City nocheck constraint FK_CountryID;
и вы добавляете новую страну
insert into dbo.Country(CountryID, Name) values(5, 'Iceland');
Вы бы в конечном итоге с этой не очень красивой картиной.
Нижняя ветвь предназначена для обновления индексированного представления. Он выполняет полное сканирование таблицы, City
чтобы выяснить, есть ли в стране CountryID = 5
строки с таблицами City
.
Когда ключ является доверенным, SQL Server знает, что в нем не может быть строк City
, соответствующих новой строке в Country
.
INSERT
создать новую строку, которая относится к несуществующей родительской строке, или если выDELETE
позже попытаетесь использовать строку, которая имеет дочерние строки?