2009-07-04 11 views
4

J'ai un problème bizarre où, après la mise en nocheck sur une contrainte étrangère et réactivant lui,plan d'exécution bizarrerie après réactivant contrainte de clé étrangère

Je reçois un même plan d'exécution hors daté qui a été utilisé avec nocheck sur. Pourquoi le serveur SQL génère-t-il un plan d'exécution comme si la contrainte étrangère FKBtoA était désactivée même après l'ajout de la vérification avec l'instruction suivante?

Pourquoi le serveur SQL générerait-il un plan d'exécution?

alter table B check constraint FKBtoA 

[Update1]
Jusqu'à présent, laissant tomber la contrainte étrangère et readding cela a fonctionné. Mais pour les tables vraiment grandes, cela semble être une exagération - Y at-il un meilleur moyen?

[REPONSE]

J'ai dû ajouter WITH CHECK dans l'instruction alter comme suit pour obtenir l'ancien plan d'exécution

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

Voici une déclaration SQL complète

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) 

Voici la capture d'écran des plans d'exécution par chaque instruction SELECT

Avant de désactiver la contrainte de clé étrangère
alt text

Après avoir désactivé la contrainte de clé étrangère
alt text

Après réactivant contrainte de clé étrangère
alt text

Répondre

7

Il est fort probable que votre contrainte soit activée mais qu'elle ne soit pas approuvée, donc il peut y avoir des lignes orphelines dans votre table enfant. Lire cet excellent article par Hugo Kornelis: Can you trust your constraints?

+0

Ah, ha! c'était la clause "with check" que j'avais besoin d'ajouter dans "alter table B add constraint" donc ça devait être "alter table B WITH CHECK add constraint ..."! Et "sys.check_constraints.is_not_trusted" a été mis à 1 quand j'ai modifié contrainte avec NOCHECK ... – Sung

+0

+1 pour "Cette réponse est utile". Je ne connaissais pas de telles choses comme des contraintes non fiables. –

+0

Voici un bon article sur le sujet - http://explainextended.com/2009/10/15/constraints-and-the-optimizer-in-sql-server-foreign-key/ – EBarr

0

Personnellement, je ne sais pas, mais je sais comment reconstruire les statistiques ...

1

Il ne semble pas y avoir de données dans ces tableaux, à en juger par les scripts que vous avez publiés et par la largeur des connecteurs dans le plan. L'analyse des plans de requête sur des tables vides est en grande partie hors de propos: lors de la lecture d'une seule page, l'optimiseur choisira presque certainement une analyse complète.

Je suppose que vous faites cela comme une sorte d'expérience, dans le monde réel, vous devriez rejoindre ces tables n'utilisent pas EXIST interne.

+0

Le plan d'exécution est resté le même que la table ait des données ou non dans mon cas ... – Sung

+0

Remus, si la contrainte FK est approuvée, l'optimiseur élimine une recherche pour le parent table, car il y a toujours une ligne parente. –

+0

à droite, ma réponse ne répond pas vraiment à la question de l'OP, tandis que la réponse d'Alex frappe à la perfection. Mon point général reste, que les plans sur des tables vides sont souvent complètement différents du plan réel utilisé sur une table peuplée. Ou en d'autres termes, voici une bonne réponse à une question différente que personne n'a posée;) –

Questions connexes