외래 키에 대한 참조 인덱스 변경


9

나는 이와 같은 것을 가지고있다 :

CREATE TABLE T1 (
    Id INT
    ...
    ,Constraint [PK_T1] PRIMARY KEY CLUSTERED [Id]
)

CREATE TABLE T2 (
    ....
    ,T1_Id INT NOT NULL
    ,CONSTRAINT [FK_T2_T1] FOREIGN KEY (T1_Id) REFERENCES T1(Id)
)

성능 및 교착 상태로 인해 T1에서 새 색인을 작성했습니다.

CREATE UNIQUE NONCLUSTERED INDEX IX_T1_Id ON T1 (Id)

그러나 FK를 참조하는 인덱스를 확인하면 클러스터형 인덱스를 계속 참조합니다.

select
    ix.index_id,
    ix.name as index_name,
    ix.type_desc as index_type_desc,
    fk.name as fk_name
from sys.indexes ix
    left join sys.foreign_keys fk on
        fk.referenced_object_id = ix.object_id
        and fk.key_index_id = ix.index_id
        and fk.parent_object_id = object_id('T2')
where ix.object_id = object_id('T1');

제약 조건을 삭제하고 다시 만들면 클러스터되지 않은 인덱스를 참조하지만 모든 t2 FK를 다시 확인합니다.

FK_T2_T1이 FK를 삭제하고 FK 검사에서 테이블을 잠그지 않고 PK_T1 대신 IX_T1_Id를 사용하도록 이것을 변경하는 방법이 있습니까?

감사!


여기에 관련 토론이 있었습니다 .
i-one

답변:


6

글쎄, 검색을 계속 한 후이 기사를 찾았습니다.

일반 쿼리와 달리 통계 업데이트, 새 인덱스 생성 또는 서버 재부팅으로 인해 새 인덱스를 선택하지 않습니다. FK를 다른 인덱스에 바인딩하는 것으로 알고있는 유일한 방법은 FK를 삭제하고 다시 만들어서 수동으로 제어 할 수있는 옵션이없는 인덱스를 자동으로 선택하도록하는 것입니다.

반면에 다른 사람이 말할 수 없다면이 작업을 수행 할 시간 창을 찾아야합니다.

감사


2

MS DOCS를 읽은 후 here .

외래 키를 수정하려면

Transact-SQL을 사용하여 FOREIGN KEY 제약 조건을 수정하려면 먼저 기존 FOREIGN KEY 제약 조건을 삭제 한 다음 새 정의로 다시 만들어야합니다. 자세한 내용은 외래 키 관계 삭제 및 외래 키 관계 만들기를 참조하십시오.

귀하의 경우 새 FK를 추가하고 이전 FK를 삭제한다고 생각합니다. 스캔을 비활성화하려면 NO CHECK옵션 을 사용할 수 있습니다

--DROP TABLE T2
--DROP TABLE T1


CREATE TABLE T1 (
    [Id] INT,
    [NAME] varchar(100), CONSTRAINT [PK_T1] PRIMARY KEY CLUSTERED (id))

CREATE TABLE T2 (
    t2_id int,
    T1_Id INT NOT NULL
    ,CONSTRAINT [FK_T2_T1] FOREIGN KEY (T1_Id) REFERENCES T1(Id)
)


CREATE UNIQUE NONCLUSTERED INDEX IX_T1_Id ON T1 (Id)


select
    ix.index_id,
    ix.name as index_name,
    ix.type_desc as index_type_desc,
    fk.name as fk_name
from sys.indexes ix
    left join sys.foreign_keys fk on
        fk.referenced_object_id = ix.object_id
        and fk.key_index_id = ix.index_id
        and fk.parent_object_id = object_id('T2')
where ix.object_id = object_id('T1');



╔══════════╦════════════╦═════════════════╦══════════╗
 index_id  index_name  index_type_desc  fk_name  
╠══════════╬════════════╬═════════════════╬══════════╣
        1  PK_T1       CLUSTERED        FK_T2_T1 
        2  IX_T1_Id    NONCLUSTERED     NULL     
╚══════════╩════════════╩═════════════════╩══════════╝




 ALTER TABLE T2
    WITH NOCHECK 
    ADD CONSTRAINT [FK_T2_T1_NEW] FOREIGN KEY(T1_Id)
    REFERENCES T1(Id)

select
    ix.index_id,
    ix.name as index_name,
    ix.type_desc as index_type_desc,
    fk.name as fk_name
from sys.indexes ix
    left join sys.foreign_keys fk on
        fk.referenced_object_id = ix.object_id
        and fk.key_index_id = ix.index_id
        and fk.parent_object_id = object_id('T2')
where ix.object_id = object_id('T1');


╔══════════╦════════════╦═════════════════╦══════════════╗
 index_id  index_name  index_type_desc    fk_name    
╠══════════╬════════════╬═════════════════╬══════════════╣
        1  PK_T1       CLUSTERED        FK_T2_T1     
        2  IX_T1_Id    NONCLUSTERED     FK_T2_T1_NEW 
╚══════════╩════════════╩═════════════════╩══════════════╝   

ALTER TABLE T2  
DROP CONSTRAINT FK_T2_T1 

select
    ix.index_id,
    ix.name as index_name,
    ix.type_desc as index_type_desc,
    fk.name as fk_name
from sys.indexes ix
    left join sys.foreign_keys fk on
        fk.referenced_object_id = ix.object_id
        and fk.key_index_id = ix.index_id
        and fk.parent_object_id = object_id('T2')
where ix.object_id = object_id('T1');


╔══════════╦════════════╦═════════════════╦══════════════╗
 index_id  index_name  index_type_desc    fk_name    
╠══════════╬════════════╬═════════════════╬══════════════╣
        1  PK_T1       CLUSTERED        NULL         
        2  IX_T1_Id    NONCLUSTERED     FK_T2_T1_NEW 
╚══════════╩════════════╩═════════════════╩══════════════╝

이것이 작동하는지 확인하십시오. 내가 시도하는 것은 FK를 하나 더 추가하여 새 인덱스가 생성 된 새 인덱스에 연결되어 이전 FK를 삭제하는 것입니다. 문제는 기존 질문을 삭제하지 말고이 옵션이 도움이되는지 확인하는 것입니다.

또한 Max Vernon의 의견에 따라 : WITH WITH NOCHECK 옵션을 사용하면 옵티마이 저가 외래 키를 신뢰할 수 없게됩니다. 어느 시점에서 ALTER TABLE을 사용하여 외래 키를 신뢰할 수 있도록 변경해야합니다. 확인으로 "

NOCHECK단지 창조의 시간에 무시하지만 무결성 contraint을 적용하면 시간의 어느 시점에서이를 실행했다.


WITH NOCHECK외래 키를 방지 할 옵션이 최적화에 의해 신뢰되고. 어느 시점에서 외래 키를 사용하여 신뢰할 수 있도록 외래 키를 변경해야합니다.ALTER TABLE ... WITH CHECK
Max Vernon

@MaxVernon은 옵션이 없다는 것을 의미합니다
Biju jose

옳은. 외래 키가 새 인덱스를 사용하도록하는 유일한 방법은 CHECK 옵션을 그대로 사용하여 외래 키를 다시 만드는 것입니다.
Max Vernon

@max Vernon, 답변을 업데이트하겠습니다
Biju jose

oficial 문서를 작성한 @Biju jose에게 감사합니다.
Mariano G
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.