2010-12-14 75 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