我讀過如果使用WITH NOCHECK添加FK,查詢優化器將不會在它生成的任何查詢計劃中使用此FK。這讓我想到如何以及爲什麼查詢優化器在生成查詢計劃時甚至會考慮FK?如果FK存在,對查詢引擎有什麼好處?查詢優化器和FK限制
回答
如果外鍵是「可信」的,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,那麼它可以對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可以安全地保持連接。
可能發生的情況是,如果您有一個查詢加入其他外鍵表,並且存在外鍵約束,則查詢引擎可以利用使用外表索引。
您可以通過查看SQL Server Management Studio中的查詢執行計劃來進行測試。它位於查詢 - >包含實際執行計劃下。嘗試一個與FK和一個WITH NOCHECK,看看不同之處。
- 1. SQL限制查詢優化
- 2. MySQL查詢優化 - 單個查詢限制
- 3. 傳統查詢優化器vs Pivotal查詢優化器
- 4. 優化PostgreSQL的查詢與ORDER BY,左連接和限制
- 5. MySQL查詢優化 - 不同,ORDER BY和限制
- 6. 選擇的MySQL查詢優化和限制在MySQL
- 7. MySQL的優化與分和限制查詢在觸發
- 8. 表別名和查詢優化器
- 9. 簡化限制和訂單AR查詢
- 10. SQL UDF和查詢優化
- 11. 查詢和表優化
- 12. MySQL表和查詢優化
- 13. 優化查詢(MySQL和PHP)
- 14. 查詢優化和級聯
- 15. 查詢加入和優化
- 16. 優化查詢和導出
- 17. NHibernate和查詢優化
- 18. 優化查詢
- 19. 優化查詢
- 20. 查詢優化
- 21. 優化查詢
- 22. 優化查詢
- 23. 查詢優化
- 24. 優化查詢
- 25. 查詢優化
- 26. 查詢優化
- 27. 查詢優化
- 28. 查詢優化
- 29. 查詢優化
- 30. 查詢優化
這可能是,但我不認爲查詢引擎需要FK來確定哪些索引可用於查詢。此外,僅僅因爲FK已經到位並不意味着FK列上存在索引。 – 2010-12-14 22:26:34
@Randy - 實際上,FK不僅意味着_target_表上存在索引,而且索引也是唯一的。這就是dsum所說的「國外表格指數」。但你說得對,它並不意味着FK表上的索引存在 - 只在FK指向的表上。 – Tadmas 2010-12-14 23:51:01