我已经读过,如果使用WITH NOCHECK添加FK,查询优化器将不会在它生成的任何查询计划中使用此FK。这让我想到了查询优化器在生成查询计划时如何以及为什么会考虑FK?如果FK到位,查询引擎会有什么好处?
答案 0 :(得分:2)
如果外键是“受信任的”,则SQL Server可以使用约束所针对的列位于另一个表的唯一索引中的事实。如果你有一个FK所针对的表的连接,你只使用键中的列,它可以删除连接。
例如,假设您有两个表:Order
和Product
,Order
表的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
的额外联接。它可以这样做,因为它知道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看看差异。