`WITH NOCHECK`을 사용하여 외래 키를 만들면 무엇이 손실됩니까?


11

나는 내가 할 경우 알고 EXISTS()FK 조회 값에 호출을하는 FK 제약 조건이 신뢰할 수있는 경우, 다음, 결과는 즉시이다.

그리고을 사용하여 FK를 만들 때와 같이 신뢰할 수없는 경우 WITH NOCHECKSQL Server는 테이블로 이동하여 값이 실제로 있는지 확인해야합니다.

내가 사용하여 잃어버린 다른 것이 NOCHECK있습니까?

답변:


13

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.


4

쿼리 최적화가 손실됩니다. 실제로 내가 기억하는 유일한 최적화는 중복 조인을 제거하는 것입니다. 예를 들어보기가있는 경우 :

select *
from Orders o
join Customers c on o.CustomerID = c.ID

그리고보기를 사용할 때 열을 사용하지 않으면 c적절한 FK가 설정되어 있으면 해당 조인을 삭제할 수 있습니다.

귀하의 EXISTS예는 중복 조인을 제거하는 특별한 경우이다. 특정 예가 실제로 관련이 있다고 생각하지 않습니다.

또한 신뢰할 수있는 제약 조건이 제공하는 엄격한 데이터 무결성을 잃게됩니다.


3

NOCHECK 옵션은 주석에 표시된 것과 정확히 일치합니다.

그것은 필요하지 않을 수도있는 새로운 관계가있는 테이블의 존재를 통해 외래 키를 반쯤 추가하는 데 주로 사용됩니다 (적어도 이해합니다).

그것은 외래 키를 가진 열이 그 안에 관련된 지정된 값과 관련이없는 값을 가질 수 있음을 의미합니다.

이는 SQL Server에 NOCHECK 옵션이있을 때 실제로 해당 키 값이 실제로 기본 키인지 확인해야한다는 것을 의미합니다. NOCHECK가 설정되어 있지 않으면 SQL Server는 이미 기본 키가 아닌 경우 테이블에 항목이 존재하지 않았기 때문에 해당 열에있는 항목이 존재한다고 가정하고 행을 삭제하지 않고 기본 키를 삭제할 수 없습니다. 질문.

간단히 NOCHECK는 실제로 어떤 것과도 관련이 있다고 믿을 수없는 외래 키입니다.

당신은 실제로 기본 키가 거기에 있다고 보장 한 신뢰 이외의 것을 잃지 않을 것입니다.


제약 조건을 처음 만든 후 외래 키가 적용되는지 여부는 명확하지 않습니다 . 당신은 당신이하려고하면 어떻게되는지 명확히 할 수 INSERT당신이하려고하면 존재하지 않는 부모 행 관련 또는 새 행 DELETE에 자식 행을 나중에이 행?
jpmc26
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.