Thay đổi chỉ mục được tham chiếu cho Khóa ngoài


9

Tôi có một cái gì đó như thế này:

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)
)

Vì lý do hiệu suất (và bế tắc), tôi đã tạo một chỉ mục mới trên T1

CREATE UNIQUE NONCLUSTERED INDEX IX_T1_Id ON T1 (Id)

Nhưng nếu tôi kiểm tra Index nào tham chiếu FK, hãy tiếp tục tham chiếu đến chỉ mục được nhóm

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');

Nếu tôi bỏ ràng buộc và tạo lại, nó tham chiếu chỉ mục không bao gồm, nhưng điều này dẫn đến việc kiểm tra lại tất cả t2 FK.

Có cách nào để thay đổi điều này để FK_T2_T1 sử dụng IX_T1_Id thay vì PK_T1 mà không bỏ FK và khóa bảng khi kiểm tra FK không?

Cảm ơn!


Có một cuộc thảo luận có liên quan ở đây .
i-một

Câu trả lời:


6

Vâng, sau khi tiếp tục tìm kiếm, tôi tìm thấy bài viết này

Không giống như một truy vấn thông thường, nó sẽ không nhận được một chỉ mục mới do số liệu thống kê được cập nhật, một chỉ mục mới được tạo hoặc thậm chí một máy chủ được khởi động lại. Cách duy nhất tôi biết để có một FK liên kết với một chỉ mục khác là thả và tạo lại FK, để nó tự động chọn chỉ mục mà không có tùy chọn nào để điều khiển thủ công.

Tuy nhiên, trừ khi ai đó có thể nói khác, tôi sẽ phải tìm một cửa sổ thời gian để thực hiện nhiệm vụ này.

Cảm ơn


2

Sau khi đọc MS DOCS tại đây .

Để sửa đổi khóa ngoại

Để sửa đổi ràng buộc FOREIGN KEY bằng cách sử dụng Transact-SQL, trước tiên bạn phải xóa ràng buộc FOREIGN KEY hiện có và sau đó tạo lại nó với định nghĩa mới. Để biết thêm thông tin, hãy xem Xóa Mối quan hệ Khóa ngoài và Tạo Mối quan hệ Khóa ngoài.

Trong trường hợp của bạn, tôi tin rằng thêm một FK mới và xóa cái cũ. Để tắt tính năng quét, bạn có thể sử dụng NO CHECKtùy chọn

--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 
╚══════════╩════════════╩═════════════════╩══════════════╝

Xem nếu điều này hoạt động, những gì tôi đang cố gắng là thêm một FK nữa để cái mới được liên kết với chỉ mục mới được tạo và loại bỏ FK cũ. Tôi biết câu hỏi không phải là bỏ câu hỏi hiện tại nhưng hãy xem liệu tùy chọn này có giúp bạn không.

Ngoài ra, theo nhận xét từ Max Vernon: "tùy chọn VỚI NOCHECK sẽ ngăn khóa ngoại được tin tưởng bởi trình tối ưu hóa. Đến một lúc nào đó, bạn phải thay đổi khóa ngoại để nó được tin cậy khi sử dụng ALTER TABLE ... VỚI KIỂM TRA "

Ý NOCHECKchí chỉ được bỏ qua tại thời điểm tạo ra nhưng để thực thi chống lại tính toàn vẹn, bạn đã chạy nó vào một lúc nào đó.


các WITH NOCHECKtùy chọn sẽ ngăn chặn các khóa ngoại được tin cậy bởi tôi ưu hoa. Tại một số điểm, bạn phải thay đổi khóa ngoại để nó được tin cậy bằng cách sử dụngALTER TABLE ... WITH CHECK
Max Vernon

@MaxVernon vì vậy điều đó có nghĩa là chúng tôi không có tùy chọn
biju jose

chính xác. Cách duy nhất để có được khóa ngoại để sử dụng chỉ mục mới là tạo lại khóa ngoại với tùy chọn CHECK còn nguyên vẹn.
Max Vernon

@max Vernon, sau đó sẽ cập nhật câu trả lời
Biju jose

Cảm ơn @Biju jose cho một tài liệu chính thức.
Mariano G
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.