私はこのようなものを持っています:
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がPK_T1ではなくIX_T1_Idを使用し、FKを削除してFKチェックでテーブルをロックする方法はありますか?
ありがとう!
さて、検索を続けた後、私は見つけました この記事
通常のクエリとは異なり、統計が更新されたり、新しいインデックスが作成されたり、サーバーが再起動したりするため、新しいインデックスは取得されません。 FKを別のインデックスにバインドすることを知っている唯一の方法は、FKを削除して再作成し、手動で制御するオプションのないインデックスを自動的に選択させることです。
そこで、誰かが別のことを言うことができない限り、私はこのタスクを実行するための時間枠を探す必要があります。
ありがとう
MS DOCSを読んだ後 ここ 。
外部キーを変更するには
Transact-SQLを使用してFOREIGN KEY制約を変更するには、まず既存のFOREIGN KEY制約を削除してから、新しい定義で再作成する必要があります。詳細については、「外部キー関係の削除」および「外部キー関係の作成」を参照してください。
あなたの場合、私は新しい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 ║
╚══════════╩════════════╩═════════════════╩══════════════╝
これが機能するかどうかを確認します。私が試みているのは、もう1つFKを追加して、新しいFKを作成された新しいインデックスにリンクし、古いFKを削除することです。問題は既存のものを削除することではありませんが、このオプションが役立つかどうかを確認してください。
また、Max Vernonからのコメントのとおり、「WITH NOCHECKオプションは、外部キーがオプティマイザによって信頼されないようにします。ある時点で、ALTER TABLE ...を使用して信頼されるように外部キーを変更する必要があります。チェック付き」
NOCHECK
は作成時にのみ無視されますが、整合性制約を強制するために、ある時点でこれを実行しました。