2010-12-14 57 views
0

我读过如果使用WITH NOCHECK添加FK,查询优化器将不会在它生成的任何查询计划中使用此FK。这让我想到如何以及为什么查询优化器在生成查询计划时甚至会考虑FK?如果FK存在,对查询引擎有什么好处?查询优化器和FK限制

回答

2

如果外键是“可信”的,SQL Server可以使用这样一个事实,即约束所针对的列在另一个表上的唯一索引中。如果您与FK所针对的表联接,并且只使用键中的列,则可以删除联接。

例如,假设您有两个表:OrderProductOrder表有ProductId这是一个外键Product.Id。然后,优化知道这个查询:

SELECT Order.Id, Product.Id 
FROM Order 
LEFT OUTER JOIN Product ON Product.Id = Order.ProductId 

...是与此相同的查询:

SELECT Order.Id, Order.ProductId 
FROM Order 

..并额外加入到Product可以被删除。它可以这样做,因为它知道Order中每行的Product中最多只有一行,并且值将相同,因此删除连接不会影响查询。

如果Order.ProductId不为NULL,那么它可以对INNER JOIN执行相同的操作。如果它是可空的,则它不能,因为它不知道在Product中会有一行,所以加入可能导致Order行被删除;这是不一样的。

但是,如果将Product.Name添加到SELECT子句中,则无论在哪种情况下都无法删除联接。

是的,我知道:它似乎不是很有用。在实践中,我并没有真正看到太多的情况下,这实际上有所作为。通常,这只是动态生成的SQL或代码生成的一个因素,其中联接是固定的,只有SELECT子句发生更改。

你可以阅读这个在这里:

http://explainextended.com/2009/10/15/constraints-and-the-optimizer-in-sql-server-foreign-key/

至于为什么WITH NOCHECK有差别,当被指定的关键不是“值得信赖的”,这意味着或许并不在列的所有值满足约束。 WITH NOCHECK只强制执行新的数据的约束;任何旧数据都可能违反假设,所以SQL Server可以安全地保持连接。

0

可能发生的情况是,如果您有一个查询加入其他外键表,并且存在外键约束,则查询引擎可以利用使用外表索引。

您可以通过查看SQL Server Management Studio中的查询执行计划来进行测试。它位于查询 - >包含实际执行计划下。尝试一个与FK和一个WITH NOCHECK,看看不同之处。

+0

这可能是,但我不认为查询引擎需要FK来确定哪些索引可用于查询。此外,仅仅因为FK已经到位并不意味着FK列上存在索引。 – 2010-12-14 22:26:34

+0

@Randy - 实际上,FK不仅意味着_target_表上存在索引,而且索引也是唯一的。这就是dsum所说的“国外表格指数”。但你说得对,它并不意味着FK表上的索引存在 - 只在FK指向的表上。 – Tadmas 2010-12-14 23:51:01