我有一个奇怪的问题,在外部约束上设置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)
但对于真正的大桌子来说,这似乎是一种矫枉过正 - 有更好的方法吗?
[ANSWER]
我必须在alter statement中添加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
声明
禁用外键约束之前
禁用外键约束后
重新启用外键约束后
答案 0 :(得分:7)
很可能您的约束已启用但不受信任,因此子表中可能存在孤立行。阅读Hugo Kornelis撰写的这篇精彩文章:Can you trust your constraints?
答案 1 :(得分:1)
这些表中似乎没有任何数据,从您发布的脚本和计划中连接器的宽度来判断。分析空表上的查询计划在很大程度上是无关紧要的:在一次单页读取时,优化器几乎肯定会选择完整扫描。
我认为你做的是某种实验,在现实世界中你应该加入那些不使用内部EXIST的表。
答案 2 :(得分:0)
我个人不知道,但我知道如何重建统计数据......