国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > SQL Server > 正文

淺談SQL Server中的三種物理連接操作(性能比較)

2024-08-31 00:44:32
字體:
來源:轉載
供稿:網友
在SQL Server中,我們所常見的表與表之間的Inner Join,Outer Join都會被執行引擎根據所選的列,數據上是否有索引,所選數據的選擇性轉化為Loop Join,Merge Join,Hash Join這三種物理連接中的一種。理解這三種物理連接是理解在表連接時解決性能問題的基礎,下面我來對這三種連接的原理,適用場景進行描述。

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

淺談SQL Server中的三種物理連接操作(性能比較)

圖2.循環嵌套連接的第二步

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

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

下面我們通過例子來看一下循環嵌套連接,利用微軟的AdventureWorks數據庫:

淺談SQL Server中的三種物理連接操作(性能比較)

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

淺談SQL Server中的三種物理連接操作(性能比較)

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

淺談SQL Server中的三種物理連接操作(性能比較)

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

淺談SQL Server中的三種物理連接操作(性能比較)

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

淺談SQL Server中的三種物理連接操作(性能比較)合并連接(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那樣不斷的查找循環內部的表。其次,Merge Join需要表連接條件中至少有一個等號查詢分析器才會去選擇Merge Join。

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

淺談SQL Server中的三種物理連接操作(性能比較)

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

淺談SQL Server中的三種物理連接操作(性能比較)

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

復制代碼 代碼如下:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 达孜县| 海门市| 沐川县| 临邑县| 神池县| 甘孜| 廉江市| 墨江| 家居| 盐边县| 轮台县| 涿州市| 宁化县| 合江县| 建德市| 利辛县| 邯郸县| 海城市| 独山县| 永城市| 射阳县| 沧源| 昭平县| 交城县| 牟定县| 三门峡市| 西乌| 茌平县| 浮梁县| 扎囊县| 宕昌县| 阜新| 平安县| 渭源县| 拜城县| 北碚区| 汶上县| 手游| 广灵县| 嵊州市| 红河县|