我读到,如果您使用WITH NOCHECK添加FK,查询优化器将不会在它生成的任何查询计划中使用此FK。这让我开始思考,在生成查询计划时,查询优化器如何以及为什么会考虑FK?如果有FK,查询引擎会有什么好处?
发布于 2010-12-15 08:01:57
如果外键是“受信任的”,则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
的额外联接。它之所以能做到这一点,是因为它知道Order
中的每一行在Product
中最多只能有一行,而且这些值是相同的,因此删除连接不会影响查询。
如果Order.ProductId
不是NULL,那么它将能够对内部连接执行相同的操作。如果它可以为空,它就不能,因为它不知道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采取安全措施,并将联接保留在那里。
发布于 2010-12-15 06:17:32
可能发生的情况是,如果您有一个连接其他外键表的查询,并且存在外键约束,则查询引擎可以利用外表索引。
您可以通过查看SQL Server Management Studio中的查询执行计划来对其进行测试。在[查询]->[包含实际执行计划]。尝试一个使用FK,另一个使用NOCHECK,看看区别。
https://stackoverflow.com/questions/4444646
复制相似问题