日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
淺談SQLServer中的三種物理連接操作

簡介

成都創(chuàng)新互聯(lián)成都網站建設定制網站開發(fā),是成都營銷推廣公司,為辦公窗簾提供網站建設服務,有成熟的網站定制合作流程,提供網站定制設計服務:原型圖制作、網站創(chuàng)意設計、前端HTML5制作、后臺程序開發(fā)等。成都網站設計熱線:028-86922220

在SQL Server中,我們所常見的表與表之間的Inner Join,Outer Join都會被執(zhí)行引擎根據(jù)所選的列,數(shù)據(jù)上是否有索引,所選數(shù)據(jù)的選擇性轉化為Loop Join,Merge Join,Hash Join這三種物理連接中的一種。理解這三種物理連接是理解在表連接時解決性能問題的基礎,下面我來對這三種連接的原理,適用場景進行描述。

嵌套循環(huán)連接(Nested Loop Join)

循環(huán)嵌套連接是最基本的連接,正如其名所示那樣,需要進行循環(huán)嵌套,嵌套循環(huán)是三種方式中***支持不等式連接的方式,這種連接方式的過程可以簡單的用下圖展示:

圖1.循環(huán)嵌套連接的***步

圖2.循環(huán)嵌套連接的第二步

由上面兩個圖不難看出,循環(huán)嵌套連接查找內部循環(huán)表的次數(shù)等于外部循環(huán)的行數(shù),當外部循環(huán)沒有更多的行時,循環(huán)嵌套結束。另外,還可以看出,這種連接方式需要內部循環(huán)的表有序(也就是有索引),并且外部循環(huán)表的行數(shù)要小于內部循環(huán)的行數(shù),否則查詢分析器就更傾向于Hash Join(會在本文后面講到)。

通過嵌套循環(huán)連接也可以看出,隨著數(shù)據(jù)量的增長這種方式對性能的消耗將呈現(xiàn)出指數(shù)級別的增長,所以數(shù)據(jù)量到一定程度時,查詢分析器往往就會采用這種方式。

下面我們通過例子來看一下循環(huán)嵌套連接,利用微軟的AdventureWorks數(shù)據(jù)庫:

圖3.一個簡單的嵌套循環(huán)連接

圖3中ProductID是有索引的,并且在循環(huán)的外部表中(Product表)符合ProductID=870的行有4688條,因此,對應的SalesOrderDetail表需要查找4688次。讓我們在上面的查詢中再考慮另外一個例子,如圖4所示。

圖4.額外的列帶來的額外的書簽查找

由圖4中可以看出,由于多選擇了一個UnitPrice列,導致了連接的索引無法覆蓋所求查詢,必須通過書簽查找來進行,這也是為什么我們要養(yǎng)成只 Select需要的列的好習慣,為了解決上面的問題,我們既可以用覆蓋索引,也可以減少所需的列來避免書簽查找。另外,上面符合ProductID的行僅僅只有5條,所以查詢分析器會選擇書簽查找,假如我們將符合條件的行進行增大,查詢分析器會傾向于表掃描(通常來說達到表中行數(shù)的1%以上往往就會進行 table scan而不是書簽查找,但這并不絕對),如圖5所示。

圖5.查詢分析器選擇了表掃描

可以看出,查詢分析器此時選擇了表掃描來進行連接,這種方式效率要低下很多,因此好的覆蓋索引和Select *都是需要注意的地方。另外,上面情況即使涉及到表掃描,依然是比較理想的情況,更糟糕的情況是使用多個不等式作為連接時,查詢分析器即使知道每一個列的統(tǒng)計分布,但卻不知道幾個條件的聯(lián)合分布,從而產生錯誤的執(zhí)行計劃,如圖6所示。

圖6.由于無法預估聯(lián)合分布,導致的偏差

由圖6中,我們可以看出,估計的行數(shù)和實際的行數(shù)存在巨大的偏差,從而應該使用表掃描但查詢分析器選擇了書簽查找,這種情況對性能的影響將會比表掃描更加巨大。具體大到什么程度呢?我們可以通過強制表掃描和查詢分析器的默認計劃進行比對,如圖7所示。

圖7.強制表掃描性能反而更好

#p#

合并連接(Merge Join)

談到合并連接,我突然想起在西雅圖參加SQL Pass峰會晚上酒吧排隊點酒,由于我和另外一哥們站錯了位置,貌似我們兩個在插隊一樣,我趕緊說:I’m sorry,i thought here is end of line。對方無不幽默的說:”It’s OK,In SQL Server,We called it merge join”。

由上面的小故事不難看出,Merge Join其實上就是將兩個有序隊列進行連接,需要兩端都已經有序,所以不必像Loop Join那樣不斷的查找循環(huán)內部的表。其次,Merge Join需要表連接條件中至少有一個等號查詢分析器才會去選擇Merge Join。

Merge Join的過程我們可以簡單用下面圖進行描述:

圖8.Merge Join***步

 Merge Join首先從兩個輸入集合中各取***行,如果匹配,則返回匹配行。加入兩行不匹配,則有較小值的輸入集合+1,如圖9所示。

圖9.更小值的輸入集合向下進1

用C#代碼表示Merge Join的話如代碼1所示。

 
 
 
 
  1. public class MergeJoin  
  2. {  
  3.     // Assume that left and right are already sorted  
  4.     public static Relation Sort(Relation left, Relation right)  
  5.     {  
  6.         Relation output = new Relation();  
  7.         while (!left.IsPastEnd() && !right.IsPastEnd())  
  8.         {  
  9.             if (left.Key == right.Key)  
  10.             {  
  11.                 output.Add(left.Key);  
  12.                 left.Advance();  
  13.                 right.Advance();  
  14.             }  
  15.             else if (left.Key < right.Key)  
  16.                 left.Advance();  
  17.             else //(left.Key > right.Key)  
  18.                 right.Advance();  
  19.         }  
  20.         return output;  
  21.     }  

代碼1.Merge Join的C#代碼表示

因此,通常來說Merge Join如果輸入兩端有序,則Merge Join效率會非常高,但是如果需要使用顯式Sort來保證有序實現(xiàn)Merge Join的話,那么Hash Join將會是效率更高的選擇。但是也有一種例外,那就是查詢中存在order by,group by,distinct等可能導致查詢分析器不得不進行顯式排序,那么對于查詢分析器來說,反正都已經進行顯式Sort了,何不一石二鳥的直接利用 Sort后的結果進行成本更小的MERGE JOIN?在這種情況下,Merge Join將會是更好的選擇。

另外,我們可以由Merge Join的原理看出,當連接條件為不等式(但不包括!=),比如說> < >=等方式時,Merge Join有著更好的效率。

下面我們來看一個簡單的Merge Join,這個Merge Join是由聚集索引和非聚集索引來保證Merge Join的兩端有序,如圖10所示。

圖10.由聚集索引和非聚集索引保證輸入兩端有序

當然,當Order By,Group By時查詢分析器不得不用顯式Sort,從而可以一箭雙雕時,也會選擇Merge Join而不是Hash Join,如圖11所示。

圖11.一箭雙雕的Merge Join

哈希匹配(Hash Join)

哈希匹配連接相對前面兩種方式更加復雜一些,但是哈希匹配對于大量數(shù)據(jù),并且無序的情況下性能均好于Merge Join和Loop Join。對于連接列沒有排序的情況下(也就是沒有索引),查詢分析器會傾向于使用Hash Join。

哈希匹配分為兩個階段,分別為生成和探測階段,首先是生成階段,***階段生成階段具體的過程可以如圖12所示。

圖12.哈希匹配的***階段

圖12中,將輸入源中的每一個條目經過散列函數(shù)的計算都放到不同的Hash Bucket中,其中Hash Function的選擇和Hash Bucket的數(shù)量都是黑盒,微軟并沒有公布具體的算法,但我相信已經是非常好的算法了。另外在Hash Bucket之內的條目是無序的。通常來講,查詢優(yōu)化器都會使用連接兩端中比較小的哪個輸入集來作為***階段的輸入源。

接下來是探測階段,對于另一個輸入集合,同樣針對每一行進行散列函數(shù),確定其所應在的Hash Bucket,在針對這行和對應Hash Bucket中的每一行進行匹配,如果匹配則返回對應的行。

通過了解哈希匹配的原理不難看出,哈希匹配涉及到散列函數(shù),所以對CPU的消耗會非常高,此外,在Hash Bucket中的行是無序的,所以輸出結果也是無序的。圖13是一個典型的哈希匹配,其中查詢分析器使用了表數(shù)據(jù)量比較小的Product表作為生成,而使用數(shù)據(jù)量大的SalesOrderDetail表作為探測。

圖13.一個典型的哈希匹配連接

上面的情況都是內存可以容納下生成階段所需的內存,如果內存吃緊,則還會涉及到Grace哈希匹配和遞歸哈希匹配,這就可能會用到TempDB從而吃掉大量的IO。這里就不細說了,有興趣的同學可以移步:http://msdn.microsoft.com/zh-cn/library/aa178403(v=SQL.80).aspx。

總結

下面我們通過一個表格簡單總結這幾種連接方式的消耗和使用場景:

  嵌套循環(huán)連接 合并連接 哈希連接
適用場景 外層循環(huán)小,內存循環(huán)條件列有序 輸入兩端都有序 數(shù)據(jù)量大,且沒有索引
CPU 低(如果沒有顯式排序)
內存 低(如果沒有顯式排序)
IO 可能高可能低 可能高可能低

理解SQL Server這幾種物理連接方式對于性能調優(yōu)來說必不可少,很多時候當篩選條件多表連接多時,查詢分析器就可能不是那么智能了,因此理解這幾種連接方式對于定位問題變得尤為重要。此外,我們也可以通過從業(yè)務角度減少查詢范圍來減少低下性能連接的可能性。

原文鏈接:http://www.cnblogs.com/CareySon/archive/2013/01/09/2853094.html


網頁題目:淺談SQLServer中的三種物理連接操作
本文來源:http://www.5511xx.com/article/cddgohc.html