5

nocheck外国の制約を設定して再度有効にした後、奇妙な問題が発生しました。

で使用されたものと同じ古い実行プランを取得してnocheckいます。

次のステートメントでチェックを再度追加した後でも、SQLサーバーが外部制約FKBtoAが無効になっているように実行プランを生成するのはなぜですか?

alter table B check constraint FKBtoA

[UPDATE1]
これまでのところ、外部制約を削除して再読み込みすることは機能していました。

alter table B drop constraint FKBtoA
alter table B add constraint FKBtoA foreign key (AID) references A(ID)

しかし、本当に大きなテーブルの場合、これはやり過ぎのようです-より良い方法はありますか?

[答え]

WITH CHECK古い実行プランを取得するには、次のような変更ステートメントを追加する必要がありました

alter table B WITH CHECK add constraint FKBtoA foreign key (AID) references A(ID)

これが完全なSQLステートメントです

create table A ( ID int identity primary key )
create table B ( 
    ID int identity primary key,
    AID int not null constraint FKBtoA references A (ID)
)

select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)

alter table B nocheck constraint FKBtoA
GO
select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)

alter table B check constraint FKBtoA
GO
select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)

SELECTこれは、各ステートメントごとの実行プランのスクリーンショットです。

外部キー制約を無効にする前
代替テキスト

外部キー制約を無効にした後
代替テキスト

外部キー制約を再度有効にした後
代替テキスト

4

3 に答える 3

7

ほとんどの場合、制約は有効になっていますが信頼されていないため、子テーブルに孤立した行が存在する可能性があります。Hugo Kornelisによるこの素晴らしい投稿を読んでください:あなたはあなたの制約を信頼できますか?

于 2009-07-04T19:43:10.700 に答える
1

投稿したスクリプトと計画のコネクタの幅の両方から判断すると、これらのテーブルにはデータがないようです。空のテーブルでクエリプランを分析することはほとんど関係ありません。1ページの読み取りで、オプティマイザはほぼ確実にフルスキャンを選択します。

これはある種の実験として行っていると思いますが、実際には、内部EXISTを使用せずにこれらのテーブルを結合する必要があります。

于 2009-07-04T18:43:55.053 に答える
0

個人的にはわかりませんが、統計を再構築する方法は知っています...

于 2009-07-04T18:01:37.010 に答える