2011-01-25 59 views
26

我正在重寫一些寫得不好的SQL查詢,並且他們正在過度使用子查詢。我正在尋找有關使用子查詢的最佳做法。何時使用SQL子查詢與標準連接?

任何幫助,將不勝感激。

+0

這不是說沒有銀彈 - 問題是這個問題太廣泛而無法合理回答。不能保證在一個數據庫(MySQL)上運行的是什麼,在另一個數據庫上運行完全一樣。最簡單的規則是,如果子查詢中的列位於最終結果集中,請使用JOIN - 這是從兩個表中獲取數據的最佳方法。否則,子查詢是好的,但相關的可能會導致問題(儘管不適用於EXISTS)。 – 2011-01-26 00:37:40

+1

你說什麼基礎上子查詢被過度使用?似乎很奇怪,決定_然後_要求提供有關使用子查詢的最佳實踐的信息。 – 2011-01-26 01:02:35

+1

[Join與子查詢]可能重複(http://stackoverflow.com/questions/2577174/join-vs-sub-query) – 2016-06-12 19:16:38

回答

39

子查詢通常很好,除非它們是從屬子查詢(也稱爲correlated subqueries)。如果您只使用獨立的子查詢並且使用適當的索引,那麼它們應該快速運行。如果您有依賴子查詢,則可能會遇到性能問題,因爲依賴子查詢通常需要針對外部查詢中的每一行運行一次。所以如果你的外部查詢有1000行,子查詢將運行1000次。另一方面,通常只需要評估一次獨立的子查詢。

如果你不知道什麼是子查詢依賴或獨立這裏的意思是一個經驗法則 - 如果你可以採取的子查詢,從上下文中刪除它,運行它,並獲得設置,那麼結果它是一個independent subquery

如果由於涉及子查詢之外的某些表而導致語法錯誤,那麼它的一個dependent subquery

一般規則當然有一些例外。例如:

  • 許多優化器可以採用從屬子查詢並找到一種方法來有效地將它作爲JOIN運行。例如,NOT EXISTS查詢可能會導致ANTI JOIN查詢計劃,因此它不一定比使用JOIN編寫查詢要慢。
  • MySQL有一個bug,IN表達式中的獨立子查詢被錯誤地標識爲從屬子查詢,因此使用了次優查詢計劃。這顯然是在最新版本的MySQL中修復的。

如果性能問題,然後衡量您的具體查詢,看看什麼最適合你。

4

不幸的是,答案在很大程度上取決於您使用的SQL Server。從理論上講,從純關係理論的角度來看,聯結更好。他們讓服務器在引擎蓋下做正確的事情,並給予他們更多的控制,因此最終可以更快。 如果服務器執行得很好。實際上,如果您通過子查詢等方式欺騙優化查詢,某些SQL服務器的性能會更好。

+0

有些子查詢也可以提升爲連接(依賴於服務器,課程)。對於大多數情況下,我發現加入「適合我的頭」更好。 – 2011-01-25 23:03:21

5

這裏沒有銀彈。每一種用法都需要獨立評估。有一些情況下,相關子查詢是普通的效率低下,下面這一個更好寫成JOIN

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc) 
from users u 

在另一方面,EXISTS和NOT EXISTS查詢會凌駕於連接。

select ... 
where NOT EXISTS (.....) 

通常快於

select ... 
FROM A LEFT JOIN B 
where B.ID is null 

然而,即使這些概括可能是不真實的任何特定模式和數據分佈。