有資料表Company,跟Products表,分別是企業表跟產品表,每個企業有0個或多個產品,現在需要選出有產品的企業,
SQL查詢如下
Select username,id From company as t
where
t.AttProperty='00000000000000001000' And t.Templateid=3
And
Exists(select * from products where products.companyid=t.id)
或
Select username,id From Company as t
where
t.AttProperty='00000000000000001000' And t.Templateid=3
And t.id in(Select companyid From Product group by companyid)
這兩句的執行計畫其實是一樣的,如:
首先是表掃描,分別掃描Company表跟Products表,掃描時會根據表的主鍵(PK)逐行進行.
1.掃描Company表:
掃描Company表時將根據ID列(Company的主鍵列),逐行取出,判斷AttProperty='00000000000000001000' 並且 Templateid=3
因為ID是主鍵,主鍵是建立叢集索引的,而叢集索引是有序的(這裡ID是int類型所以按數字大小徘序),掃描完Company表的結果是一個按ID排序的記錄集Rs(ID,User)
2.掃描Products表並構建Hash表:
同樣根據Products表的主鍵(也是名為ID的列)逐行取出,根據每行的ComanpyID(CompanyID是對應於Company.ID的外鍵),建立Hash表,將從Products中取出的每一行根據CompanyID添加到Hash中來,最後我們就得到一個按CompanyID為鍵進行檢索的Hash表了,由於掃描Products表使用的Products.ID的順序,因此最後得到Hash表中CompanyID並不是按順序排列的.
3.排序Hash表
根據CompanyID對Hash表進行排序
4.Merge join
Merge Join 是將兩個已經排好序的表,進行匹配,邏輯上就是一個inner join, 排序好的表進行匹配時只需選擇一記錄數較小的表(取名為A),取其第一個記錄,使用這個記錄從另外一張表(取名為B)進行尋找,由於是排序好的序列,可以進行二分尋找,找到後,記下B表此記錄的位置(設定位indexB0) 這樣A表第二條記錄在B表進行二分尋找時,其左索引就從IndexB0開始.如果A表的某條記錄在B表中無法匹配那麼整個匹配就完成了.
當然在A表記錄跟B表記錄匹配度很高時(比方完全一樣)那麼做順序尋找可能效率更高,當然我無法知道MSSQL內部具體的實現,以上只是自己的猜測而已,如有不當,望多兼諒!
可以看到SQL語句最後變成集合操作,而集合操作中又離不開,排序,尋找...這些基本操作,學校出來好幾年了,每天接觸的多是SQL語句,今天默然發現他們早在SQL中了,-_"