Sql-Server
當我使用“WITH NOCHECK”創建外鍵時會失去什麼?
我知道,如果我
EXISTS()
對 FK 查找值進行呼叫,那麼,如果該 FK 約束是可信的,那麼結果是立竿見影的。如果它不被信任(比如當我使用創建 FK 時
WITH NOCHECK
),那麼 SQL Server 必須去檢查表以查看該值是否確實存在。使用還有什麼我會失去的
NOCHECK
嗎?
正如您在
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
.
您正在失去查詢優化。實際上,我記得的唯一優化是消除冗餘連接。例如,如果您有一個視圖:
select * from Orders o join Customers c on o.CustomerID = c.ID
並且在使用視圖時,
c
如果設置了正確的 FK,則可以刪除該連接的列。您的
EXISTS
範例是刪除冗餘連接的特例。我認為這個特定的例子實際上並不相關。您還會失去可信約束提供的嚴格數據完整性。