查询优化器和FK约束

时间:2010-12-14 21:53:09

标签: sql-server

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

2 个答案:

答案 0 :(得分:2)

如果外键是“受信任的”,则SQL Server可以使用约束所针对的列位于另一个表的唯一索引中的事实。如果你有一个FK所针对的表的连接,你只使用键中的列,它可以删除连接。

例如,假设您有两个表:OrderProductOrder表的ProductIdProduct.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的额外联接。它可以这样做,因为它知道Product中每行Order中最多只有一行,并且值将相同,因此删除连接不会影响查询。

如果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可以安全地使用它并保持连接。

答案 1 :(得分:0)

如果您有一个连接其他外键表的查询,并且存在外键约束,则查询引擎可以利用外部表索引。

您可以通过查看SQL Server Management Studio中的查询执行计划来测试它。它位于Query-> Include Actual Execution Plan下。尝试一个用FK和一个WITH NOCHECK看看差异。