1. 程式人生 > 其它 >對比SQL中簡單巢狀查詢與非巢狀查詢的異同

對比SQL中簡單巢狀查詢與非巢狀查詢的異同

GPS平臺、網站建設、軟體開發、系統運維,找森大網路科技!
https://cnsendnet.taobao.com
來自森大科技官方部落格
http://www.cnsendblog.com/index.php/?p=2159

本文將討論的是SQL中簡單巢狀查詢與非巢狀查詢的異同,通過這些來更加深刻理解SQL語句。

某天的工作是修復某個專案的bug,接著就發現,其sql極其混亂,有非常多的left join和in操作,還有巢狀查詢(只有一個表的巢狀查詢)。不知道看到過哪裡的資料說,巢狀查詢速度慢,於是我把全部巢狀查詢都改成join的形式,巢狀查詢裡面的where條件,我都寫到join...on後面去了。突然一個想法冒出來:篩選條件跟在join...on後面 和 跟在整個sql語句最後面的where後面有什麼區別呢?還有巢狀查詢真的慢麼?於是便有下面的測試產生,資料庫環境為MS SQL 2005。

一,inner join

先看看非巢狀查詢:

  1. a.select*fromt1
  2. innerjoint2ont1.id=t2.id
  3. innerjoint3ont1.id=t3.id
  4. wheret1.a=1andt2.b=1andt3.c=1
  5. b.select*fromt1
  6. innerjoint2ont1.id=t2.idandt2.b=1
  7. innerjoint3ont1.id=t3.id
  8. wheret1.a=1andt3.c=1
  9. 10.

11. c.select*fromt1

12. innerjoint2ont1.id=t2.idandt2.b=1

13. innerjoint3ont1.id=t3.idandt3.c=1

14. wheret1.a=1

在上面三個非巢狀查詢,讓“and t2.b=1”和“and t3.c=1”分別在join...on和where之間遊走,用Management Studio選中“包含實際的執行計劃”並執行這三條語句,都得出下面這個執行計劃。

三個“聚集索引掃描”的謂詞從上到下分別是:

1.t3.c=1

2.t1.a=1 (seek謂詞:t1.id=t3.id)

3.t2.b=1(seek謂詞:t2.id=t3.id)

故可以認為:在MS SQL2005中,條件跟在join...on後面和 跟在where後面是等價的。

接著看巢狀查詢

  1. d.select*fromt1
  2. inner
    join(select*fromt2wheret2.b=1)aont1.id=a.id
  3. innerjoint3ont1.id=t3.id
  4. wheret1.a=1andt3.c=1
  5. e.select*fromt1
  6. innerjoin(select*fromt2wheret2.b=1)aont1.id=a.id
  7. innerjoin(select*fromt3wheret3.c=1)bont1.id=b.id
  8. wheret1.a=1
  9. 10.

11. f.elect*fromt1

12. innerjoin(selectt3.id,t2.b,t3.cfromt3innerjoint2ont2.id=t3.idwheret2.b=1andt3.c=1)aont1.id=a.id

13. wheret1.a=1

第一句sql語句把t2的查詢變成子查詢,第二句sql語句把t2,t3分別變成子查詢,第三句把t2和t3的查詢合成一個子查詢,再看看實際的執行計劃:

跟上面非巢狀查詢的執行計劃一模一樣。

故可以認為:簡單(注意是簡單的,複雜的情況得另外考慮)巢狀查詢和其相對應的非巢狀查詢形式,執行效率是一樣的(網上一些文章指出這是MS SQL優化器針對這些巢狀查詢進行了優化)。

接著,在上面兩個執行計劃的圖中又發現一個小問題,為什麼明明是select t1 inner join t2 inner join t3,執行計劃卻把t1和t3先inner join(t1.id = t3.id)再跟t2 inner join(t2.id = t3.id)起來?

經過三個表,四個表,五個表進行連線測試,發現這些順序都是不確定的。很可能這些順序是根據SQL優化器內的演算法所決定的,由於沒有原始碼,所以無從考究。

(感謝Keep Walking的補充:

“可以指定順序,force order選項,和keep plan選項

數量級,索引,統計的不同都可以導致順序變化”。

我Google了一下option force order和option keep plan,發現SQL優化器做了很多事情,在這文章就不列出來了,大家有興趣可以Goo一下。)

PS:

1.經測試,在join on後面t1.id = t2.id與t2.id = t1.id等價

GPS平臺、網站建設、軟體開發、系統運維,找森大網路科技!
https://cnsendnet.taobao.com
來自森大科技官方部落格
http://www.cnsendblog.com/index.php/?p=2159